Exemple #1
0
    def _log_clicked(self):
        """
        Change scale and settings to log / lin when log setting is changed
        Update min / max settings when lineEdits have been edited
        """
        self.log = self.chkLog.isChecked()
        if self.sender().objectName() == 'chkLog': # clicking chkLog triggered the slot
            if self.log:
                self.ledBottom.setText(str(self.zmin_dB))
                self.zmax_dB = np.round(20 * log10(self.zmax), 2)
                self.ledTop.setText(str(self.zmax_dB))
                self.lblTopdB.setVisible(True)
                self.lblBottomdB.setVisible(True)
            else:
                self.ledBottom.setText(str(self.zmin))
                self.zmax = np.round(10**(self.zmax_dB / 20), 2)
                self.ledTop.setText(str(self.zmax))
                self.lblTopdB.setVisible(False)
                self.lblBottomdB.setVisible(False)
                
        else: # finishing a lineEdit field triggered the slot
            if self.log:
                self.zmin_dB = safe_eval(self.ledBottom.text(), self.zmin_dB, return_type='float')
                self.ledBottom.setText(str(self.zmin_dB))
                self.zmax_dB = safe_eval(self.ledTop.text(), self.zmax_dB, return_type='float')
                self.ledTop.setText(str(self.zmax_dB))
            else:
                self.zmin = safe_eval(self.ledBottom.text(), self.zmin, return_type='float')
                self.ledBottom.setText(str(self.zmin))
                self.zmax = safe_eval(self.ledTop.text(), self.zmax, return_type='float')
                self.ledTop.setText(str(self.zmax))

        self.draw()
Exemple #2
0
 def _update_UI(self):
     """
     Update UI when line edit field is changed (here, only the text is read
     and converted to integer) and resize the textfields according to content.
     """
     self.delays = safe_eval(self.led_delays.text(), self.delays, return_type='int', sign='pos')
     self.led_delays.setText(str(self.delays))        
     self.stages = safe_eval(self.led_stages.text(), self.stages, return_type='int', sign='pos')
     self.led_stages.setText(str(self.stages))
     
     self._store_entries()
Exemple #3
0
    def _update_UI(self):
        """
        Update UI and info_doc when one of the comboboxes or line edits is 
        changed.
        """
        self.fir_window_name = str(self.cmb_firwin_win.currentText()).lower()
        self.alg = str(self.cmb_firwin_alg.currentText())

        mod_ = import_module('scipy.signal')
#        mod = __import__('scipy.signal') # works, but not with the next line
        
         # construct window class, e.g. scipy.signal.boxcar :
        class_ = getattr(mod_, self.fir_window_name)
        win_doc = getattr(class_, '__doc__') # read docstring attribute from class
        
        self.info_doc = []
        self.info_doc.append('firwin()\n========')
        self.info_doc.append(sig.firwin.__doc__)
        self.info_doc.append(self.fir_window_name + '()' +'\n' + 
                                        '=' * (len(self.fir_window_name) + 2))
        self.info_doc.append(win_doc)
        
        self.winArgs = inspect.getargspec(class_)[0] # return args of window
        # and remove common args for all window types ('sym' and 'M'):
        self.winArgs = [arg for arg in self.winArgs if arg not in {'sym', 'M'}]

        
        # make edit boxes and labels for additional parameters visible if needed
        # and construct self.firWindow as a tuple consisting of a string with 
        # the window name and optionally one or two float parameters. 
        # If there are no additional parameters, just pass the window name string.
        N_args = len(self.winArgs)
        self.lbl_firwin_1.setVisible(N_args > 0)
        self.led_firwin_1.setVisible(N_args > 0)
        self.lbl_firwin_2.setVisible(N_args > 1)
        self.led_firwin_2.setVisible(N_args > 1)
            
        if N_args > 1 :
            self.lbl_firwin_2.setText(self.winArgs[1] + ":")
            self.firWindow = (self.fir_window_name,
                                      safe_eval(self.led_firwin_1.text(), return_type='float'), 
                                      safe_eval(self.led_firwin_2.text(), return_type='float'))
        elif N_args > 0 :
            self.lbl_firwin_1.setText(self.winArgs[0] + ":")
            self.firWindow = (self.fir_window_name,
                                      safe_eval(self.led_firwin_1.text(), return_type='float'))
        else:
            self.firWindow = self.fir_window_name

        # sig_tx -> select_filter -> filter_specs
        self.sig_tx.emit({'sender':__name__, 'filt_changed':'firwin'})
Exemple #4
0
 def _store_q_settings(self):
     """
     Read out the settings of the quantization comboboxes and store them in
     the filter dict. Update the fixpoint object.
     """
     fb.fil[0]['q_coeff'] = {
             'WI':safe_eval(self.ui.ledWI.text(), self.myQ.WI, return_type='int'),
             'WF':safe_eval(self.ui.ledWF.text(), self.myQ.WF, return_type='int', sign='pos'),
             'quant':qstr(self.ui.cmbQuant.currentText()),
             'ovfl':qstr(self.ui.cmbQOvfl.currentText()),
             'frmt':qstr(self.ui.cmbFormat.currentText()),
             'scale':qstr(self.ui.ledScale.text())
             }
     self._load_q_settings() # update widgets and the fixpoint object self.myQ
Exemple #5
0
        def _store_entry(source):
            if self.spec_edited:
                if source.objectName() == "stimFreq1":
                   self.f1 = safe_eval(source.text(), self.f1 * fb.fil[0]['f_S'],
                                            return_type='float') / fb.fil[0]['f_S']
                   source.setText(str(params['FMT'].format(self.f1 * fb.fil[0]['f_S'])))

                elif source.objectName() == "stimFreq2":
                   self.f2 = safe_eval(source.text(), self.f2 * fb.fil[0]['f_S'],
                                            return_type='float') / fb.fil[0]['f_S']
                   source.setText(str(params['FMT'].format(self.f2 * fb.fil[0]['f_S'])))

                self.spec_edited = False # reset flag
                self.draw()
Exemple #6
0
    def update_N(self, dict_sig=None):
        """
        Update values for self.N and self.N_start from the QLineEditWidget
        """
        self.N_start = safe_eval(self.led_N_start.text(), 0, return_type='int', sign='pos')
        self.led_N_start.setText(str(self.N_start))
        N_user = safe_eval(self.led_N_points.text(), 0, return_type='int', sign='pos')
        if N_user == 0: # automatic calculation
            self.N = self.calc_n_points(N_user) # widget remains set to 0
        else:
            self.N = N_user
            self.led_N_points.setText(str(self.N)) # update widget

        self.N_end = self.N + self.N_start # total number of points to be calculated: N + N_start

        self._update_win_fft(dict_sig)
Exemple #7
0
    def _set_filter_order(self, enb_signal=False):
        """
        Triggered when either ledOrderN or chkMinOrder are edited:
        - copy settings to fb.fil[0]
        - emit sigFiltChanged if enb_signal is True
        """
        # Determine which subwidgets are _enabled_
        if self.chkMinOrder.isVisible():
            self.ledOrderN.setEnabled(not self.chkMinOrder.isChecked())
            self.lblOrderN.setEnabled(not self.chkMinOrder.isChecked())

            if self.chkMinOrder.isChecked() == True:
                # update in case N has been changed outside this class
                self.ledOrderN.setText(str(fb.fil[0]['N']))
                fb.fil[0].update({'fo' : 'min'})

            else:
                fb.fil[0].update({'fo' : 'man'})

        else:
            self.lblOrderN.setEnabled(self.fo == 'man')
            self.ledOrderN.setEnabled(self.fo == 'man')

        # read manual filter order, convert to positive integer and store it
        # in filter dictionary.
        ordn = safe_eval(self.ledOrderN.text(), fb.fil[0]['N'], return_type='int', sign='pos')
        ordn = ordn if ordn > 0 else 1
        self.ledOrderN.setText(str(ordn))
        fb.fil[0].update({'N' : ordn})

        if enb_signal:
            logger.debug("Emit sigFiltChanged") 
            self.sigFiltChanged.emit() # -> filter_specs
Exemple #8
0
    def _W_changed(self):
        """
        Set fractional and integer length `WF` and `WI` when wordlength Ẁ` has
        been changed. Try to preserve `WI` or `WF` settings depending on the
        number format (integer or fractional).
        """
        
        # if self.ui.ledW.isModified() ... self.ui.ledW.setModified(False)
        W = safe_eval(self.ui.ledW.text(), self.myQ.W, return_type='int', sign='pos')

        if W < 2:
            logger.warn("W must be > 1, restoring previous value.")
            W = self.myQ.W # fall back to previous value
        self.ui.ledW.setText(str(W))

        if qget_cmb_box(self.ui.cmbQFrmt) == 'qint': # integer format, preserve WI bits
            WI = W - self.myQ.WF - 1
            self.ui.ledWI.setText(str(WI))
            self.ui.ledScale.setText(str(1 << (W-1)))
        else: # fractional format, preserve WF bit setting
            WF = W - self.myQ.WI - 1
            if WF < 0:
                self.ui.ledWI.setText(str(W - 1))
                WF = 0
            self.ui.ledWF.setText(str(WF))

        self._store_q_settings()
        self._refresh_table()
Exemple #9
0
 def _set_eps(self):
     """
     Set all coefficients = 0 in self.ba with a magnitude less than eps
     and refresh QTableWidget
     """
     self.ui.eps = safe_eval(self.ui.ledEps.text(), return_type='float', sign='pos', alt_expr=self.ui.eps)
     self.ui.ledEps.setText(str(self.ui.eps))
Exemple #10
0
    def setModelData(self, editor, model, index):
        """
        When editor has finished, read the updated data from the editor,
        convert it back to floating point format and store it in both the model
        (= QTableWidget) and in self.ba. Finally, refresh the table item to 
        display it in the selected format (via `float2frmt()`).

        editor: instance of e.g. QLineEdit
        model:  instance of QAbstractTableModel
        index:  instance of QModelIndex
        """

        # check for different editor environments if needed and provide a default:
#        if isinstance(editor, QtGui.QTextEdit):
#            model.setData(index, editor.toPlainText())
#        elif isinstance(editor, QComboBox):
#            model.setData(index, editor.currentText())
#        else:
#            super(ItemDelegate, self).setModelData(editor, model, index)
        if self.parent.myQ.frmt == 'float':
            data = safe_eval(qstr(editor.text()), 
                             self.parent.ba[index.column()][index.row()], return_type='auto') # raw data without fixpoint formatting
        else:
            data = self.parent.myQ.frmt2float(qstr(editor.text()),
                                    self.parent.myQ.frmt) # transform back to float

        model.setData(index, data)                          # store in QTableWidget
        self.parent.ba[index.column()][index.row()] = data  # and in self.ba
        qstyle_widget(self.parent.ui.butSave, 'changed')
        self.parent._refresh_table_item(index.row(), index.column()) # refresh table entry
Exemple #11
0
    def _set_number_format(self):
        """
        Set one of three number formats: Integer, fractional, normalized fractional
        """

        qfrmt = qget_cmb_box(self.ui.cmbQFrmt)
        is_qfrac = False
        W = safe_eval(self.ui.ledW.text(), self.myQ.W, return_type='int', sign='pos')
        if qfrmt == 'qint':
            self.ui.ledWI.setText(str(W - 1))
            self.ui.ledWF.setText("0")
            self.ui.ledScale.setText(str(1 << (W-1)))
        elif qfrmt == 'qnfrac': # normalized fractional format
            self.ui.ledWI.setText("0")
            self.ui.ledWF.setText(str(W - 1))
            self.ui.ledScale.setText("1")
        else: # qfrmt == 'qfrac':
            is_qfrac = True

        self.ui.ledWI.setEnabled(is_qfrac)
        self.ui.lblDot.setEnabled(is_qfrac)
        self.ui.ledWF.setEnabled(is_qfrac)
        self.ui.ledW.setEnabled(not is_qfrac)
        self.ui.ledScale.setEnabled(is_qfrac)

        self._store_q_settings()
        self._refresh_table()
Exemple #12
0
    def _store_q_settings(self):
        """
        Read out the settings of the quantization comboboxes and store them in
        the filter dict. Update the fixpoint object and refresh table
        """
        fb.fil[0]['q_coeff'] = {
                'WI':safe_eval(self.ui.ledWI.text(), self.myQ.WI, return_type='int'),
                'WF':safe_eval(self.ui.ledWF.text(), self.myQ.WF, return_type='int', sign='pos'),
                'quant':qstr(self.ui.cmbQuant.currentText()),
                'ovfl':qstr(self.ui.cmbQOvfl.currentText()),
                'frmt':qstr(self.ui.cmbFormat.currentText()),
                'scale':qstr(self.ui.ledScale.text())
                }
        self.sig_tx.emit({'sender':__name__, 'view_changed':'q_coeff'})

        self._load_q_settings() # update widgets and the fixpoint object self.myQ
        self._refresh_table()
Exemple #13
0
 def _store_gain(self, source):
     """
     When the textfield of `source` has been edited (flag `self.spec_edited` =  True),
     store it in the shadow dict. This is triggered by `QEvent.focusOut` or
     RETURN key.
     """
     if self.spec_edited:
         self.zpk[2] = safe_eval(source.text(), alt_expr = str(self.zpk[2]))
         self.spec_edited = False # reset flag
Exemple #14
0
 def _set_scale(self):
     """
     Set scale for calculating floating point value from fixpoint representation
     and vice versa
     """
     # if self.ui.ledScale.isModified() ... self.ui.ledScale.setModified(False)
     scale = safe_eval(self.ui.ledScale.text(), self.myQ.scale, return_type='float', sign='pos')
     self.ui.ledScale.setText(str(scale))
     self._store_q_settings()
Exemple #15
0
 def _store_entry():
     """
     Update filter dictionary, set line edit entry with reduced precision
     again.
     """
     if self.spec_edited:
         fb.fil[0].update({'f_S':safe_eval(source.text(), fb.fil[0]['f_S'])})
         self._freq_range(emit_sig_range = False) # update plotting range
         self.sigSpecsChanged.emit() # -> input_widgets
         self.spec_edited = False # reset flag, changed entry has been saved
Exemple #16
0
 def _store_entry():
     """
     Update filter dictionary, set line edit entry with reduced precision
     again.
     """
     if self.spec_edited:
         fb.fil[0].update({'f_S':safe_eval(source.text(), fb.fil[0]['f_S'])})
         # TODO: ?!
         self._freq_range(emit_sig_range = False) # update plotting range 
         self.sig_tx.emit({'sender':__name__, 'view_changed':'f_S'})
         self.spec_edited = False # reset flag, changed entry has been saved
Exemple #17
0
 def _store_entry(self, widget):
     """
     When the textfield of `widget` has been edited (`self.spec_edited` =  True),
     store the weight spec in filter dict. This is triggered by `QEvent.focusOut`
     """
     if self.spec_edited:
         w_label = str(widget.objectName())
         w_value = safe_eval(widget.text(), fb.data_old)
         fb.fil[0].update({w_label:w_value})
         self.sigSpecsChanged.emit() # -> filter_specs
         self.spec_edited = False # reset flag
     self.load_dict()
Exemple #18
0
    def frmt2cmplx(self, text, default=0.):
        """
        Convert format defined by cmbPZFrmt to real or complex
        """
        conv_error = False
        text = qstr(text).replace(" ", "") # convert to "proper" string without blanks
        if qget_cmb_box(self.ui.cmbPZFrmt) == 'cartesian':
            return safe_eval(text, default, return_type='auto')
        else:
            polar_str = text.split('*' + self.angle_char, 1)
            if len(polar_str) < 2: # input is real or imaginary
                r = safe_eval(re.sub('['+self.angle_char+'<∠°]','', text), default, return_type='auto')
                x = r.real
                y = r.imag
            else:
                r = safe_eval(polar_str[0], sign='pos')
                if safe_eval.err > 0:
                    conv_error = True

                if "°" in polar_str[1]:
                    scale = np.pi / 180. # angle in degrees
                elif re.search('π$|pi$', polar_str[1]):
                    scale = np.pi
                else:
                    scale = 1. # angle in rad

                # remove right-most special characters (regex $)
                polar_str[1] = re.sub('['+self.angle_char+'<∠°π]$|rad$|pi$', '', polar_str[1])
                phi = safe_eval(polar_str[1]) * scale
                if safe_eval.err > 0:
                    conv_error = True

                if not conv_error:
                    x = r * np.cos(phi)
                    y = r * np.sin(phi)
                else:
                    x = default.real
                    y = default.imag
                    logger.error("Expression {0} could not be evaluated.".format(text))
            return x + 1j * y
Exemple #19
0
    def cmplx2frmt(self, text, places=-1):
        """
        Convert number "text" (real or complex or string) to the format defined 
        by cmbPZFrmt.
        
        Returns: 
            string
        """
        # convert to "normal" string and prettify via safe_eval:
        data = safe_eval(qstr(text), return_type='auto')
        frmt = qget_cmb_box(self.ui.cmbPZFrmt) # get selected format

        if places == -1:
            full_prec = True
        else:
            full_prec = False

        if frmt == 'cartesian' or not (type(data) == complex):
            if full_prec:
                return "{0}".format(data)
            else:
                return "{0:.{plcs}g}".format(data, plcs=places)

        elif frmt == 'polar_rad':
            r, phi = np.absolute(data), np.angle(data, deg=False)
            if full_prec:
                return "{r} * {angle_char}{p} rad"\
                    .format(r=r, p=phi, angle_char=self.angle_char)
            else:
                return "{r:.{plcs}g} * {angle_char}{p:.{plcs}g} rad"\
                    .format(r=r, p=phi, plcs=places, angle_char=self.angle_char)

        elif frmt == 'polar_deg':
            r, phi = np.absolute(data), np.angle(data, deg=True)
            if full_prec:
                return "{r} * {angle_char}{p}°"\
                    .format(r=r, p=phi, angle_char=self.angle_char)
            else:
                return "{r:.{plcs}g} * {angle_char}{p:.{plcs}g}°"\
                    .format(r=r, p=phi, plcs=places, angle_char=self.angle_char)

        elif frmt == 'polar_pi':
            r, phi = np.absolute(data), np.angle(data, deg=False) / np.pi
            if full_prec:
                return "{r} * {angle_char}{p} pi"\
                    .format(r=r, p=phi, angle_char=self.angle_char)
            else:
                return "{r:.{plcs}g} * {angle_char}{p:.{plcs}g} pi"\
                    .format(r=r, p=phi, plcs=places, angle_char=self.angle_char)

        else:
            logger.error("Unknown format {0}.".format(frmt))
Exemple #20
0
 def _store_entry(self, event_source):
     """
     _store_entry is triggered by `QEvent.focusOut` in the eventFilter:        
     When the textfield of `widget` has been edited (`self.spec_edited` =  True),
     sort and store all entries in filter dict, then reload the text fields. 
     Finally, emit a SpecsChanged signal.
     """
     if self.spec_edited:
         f_label = str(event_source.objectName())
         f_value = safe_eval(event_source.text(), fb.data_old) / fb.fil[0]['f_S']
         fb.fil[0].update({f_label:f_value})
         self.sort_dict_freqs()
         self.sigSpecsChanged.emit() # -> filter_specs
         self.spec_edited = False # reset flag
Exemple #21
0
    def _log_mode_time(self):
        """
        Select / deselect log. mode for time domain and update self.bottom_t
        """
        log = self.ui.chk_log_time.isChecked()
        self.ui.lbl_log_bottom_time.setVisible(log)
        self.ui.led_log_bottom_time.setVisible(log)
        self.ui.lbl_dB_time.setVisible(log)
        if log:
            self.bottom_t = safe_eval(self.ui.led_log_bottom_time.text(), self.bottom_t,
                                    return_type='float', sign='neg')
            self.ui.led_log_bottom_time.setText(str(self.bottom_t))
        else:
            self.bottom_t = 0

        self.draw_impz()
Exemple #22
0
 def _store_entry(self, widget):
     """
     When the textfield of `widget` has been edited (`self.spec_edited` =  True),
     store the weight spec in filter dict. This is triggered by `QEvent.focusOut`
     """
     if self.spec_edited:
         w_label = str(widget.objectName())
         w_value = safe_eval(widget.text(), fb.data_old, sign='pos')
         if w_value < 1:
             w_value = 1
         if w_value > 1.e6:
             w_value = 1.e6
         fb.fil[0].update({w_label:w_value})
         self.sig_tx.emit({'sender':__name__, 'specs_changed':'w_specs'})
         self.spec_edited = False # reset flag
     self.load_dict()
Exemple #23
0
    def _log_mode_freq(self):
        """
        Select / deselect log. mode for frequency domain and update self.bottom_f
        """

        log = self.ui.chk_log_freq.isChecked()
        self.ui.lbl_log_bottom_freq.setVisible(log)
        self.ui.led_log_bottom_freq.setVisible(log)
        self.ui.lbl_dB_freq.setVisible(log)
        if log:
            self.bottom_f = safe_eval(self.ui.led_log_bottom_freq.text(), self.bottom_f,
                                    return_type='float', sign='neg')
            self.ui.led_log_bottom_freq.setText(str(self.bottom_f))
        else:
            self.bottom_f = 0
            
        self.draw_impz()
Exemple #24
0
    def _update_UI(self):
        """
        Update UI when line edit field is changed (here, only the text is read
        and converted to integer) and store parameter settings in filter 
        dictionary
        """
        self.grid_density = safe_eval(self.led_remez_1.text(), self.grid_density, 
                                      return_type='int', sign='pos' )
        self.led_remez_1.setText(str(self.grid_density))

        if not 'wdg_fil' in fb.fil[0]:
            fb.fil[0].update({'wdg_fil':{}})
        fb.fil[0]['wdg_fil'].update({'equiripple':
                                        {'grid_density':self.grid_density}
                                    })
        
        self.sigFiltChanged.emit() # -> select_filter -> filter_specs
Exemple #25
0
    def _log_mode_time(self):
        """
        Select / deselect log. mode for time domain and update self.bottom_t
        """
        log = self.ui.chk_log_time.isChecked()
        self.ui.lbl_log_bottom_time.setVisible(log)
        self.ui.led_log_bottom_time.setVisible(log)
        self.ui.lbl_dB_time.setVisible(log)
        if log:
            self.bottom_t = safe_eval(self.ui.led_log_bottom_time.text(),
                                      self.bottom_t,
                                      return_type='float',
                                      sign='neg')
            self.ui.led_log_bottom_time.setText(str(self.bottom_t))
        else:
            self.bottom_t = 0

        self.draw_impz()
Exemple #26
0
    def displayText(self, text, locale):
        """
        Display `text` with selected fixpoint base and number of places

        text:   string / QVariant from QTableWidget to be rendered
        locale: locale for the text

        The instance parameter myQ.ovr_flag is set to +1 or -1 for positive /
        negative overflows, else it is 0.
        """
        data_str = qstr(text) # convert to "normal" string

        if self.parent.myQ.frmt == 'float':
            data = safe_eval(data_str, return_type='auto') # convert to float
            return "{0:.{1}g}".format(data, params['FMT_ba'])
        else:
            return "{0:>{1}}".format(self.parent.myQ.float2frmt(data_str),
                                        self.parent.myQ.places)
Exemple #27
0
    def _store_entry(self, source):
        """
        When the textfield of `source` has been edited (flag `self.spec_edited` =  True),
        transform the amplitude spec back to linear unit setting and store it
        in filter dict.
        This is triggered by `QEvent.focusOut`

        Spec entries are *always* stored in linear units; only the
        displayed values are adapted to the amplitude unit, not the dictionary!
        """
        if self.spec_edited:
            unit = str(self.cmbUnitsA.currentText())
            filt_type = fb.fil[0]['ft']
            amp_label = str(source.objectName())
            amp_value = safe_eval(source.text(), fb.data_old)
            fb.fil[0].update({amp_label:unit2lin(amp_value, filt_type, amp_label, unit)})
            self.sigSpecsChanged.emit() # -> filter_specs
            self.spec_edited = False # reset flag
        self.load_dict()
Exemple #28
0
    def _copy_item(self):
        """
        Copy the value from the current table item to self.zpk and normalize /
        update the gain. This is triggered every time a table item is edited.
        When no item was selected, only the gain is updated.

        Triggered by  `tblPZ.cellChanged` and `cmbNorm.activated`

        """
        col = self.tblPZ.currentIndex().column()
        row = self.tblPZ.currentIndex().row()
        item = self.tblPZ.item(row, col)

        if item:
            if item.text() != "":
                self.zpk[col][row] = safe_eval(item.text())
            else:
                self.zpk[col][row] = 0.
        self._normalize_gain()
Exemple #29
0
    def _log_mode_freq(self):
        """
        Select / deselect log. mode for frequency domain and update self.bottom_f
        """

        log = self.ui.chk_log_freq.isChecked()
        self.ui.lbl_log_bottom_freq.setVisible(log)
        self.ui.led_log_bottom_freq.setVisible(log)
        self.ui.lbl_dB_freq.setVisible(log)
        if log:
            self.bottom_f = safe_eval(self.ui.led_log_bottom_freq.text(),
                                      self.bottom_f,
                                      return_type='float',
                                      sign='neg')
            self.ui.led_log_bottom_freq.setText(str(self.bottom_f))
        else:
            self.bottom_f = 0

        self.draw_impz()
Exemple #30
0
 def _update_noi(self):
     """ Update type + value + label for self.noi for noise"""
     self.noise = qget_cmb_box(self.cmbNoise, data=False).lower()
     self.lblNoi.setVisible(self.noise!='none')
     self.ledNoi.setVisible(self.noise!='none')
     if self.noise!='none':
         self.noi = safe_eval(self.ledNoi.text(), 0, return_type='float', sign='pos')
         self.ledNoi.setText(str(self.noi))
         if self.noise == 'gauss':
             self.lblNoi.setText(to_html("&sigma; =", frmt='bi'))
             self.ledNoi.setToolTip("<span>Standard deviation of statistical process,"
                                    "noise power is <i>P</i> = &sigma;<sup>2</sup></span>")
         elif self.noise == 'uniform':
             self.lblNoi.setText(to_html("&Delta; =", frmt='bi'))
             self.ledNoi.setToolTip("<span>Interval size for uniformly distributed process "
                                    "(e.g. quantization step size for quantization noise), "
                                    "centered around 0. Noise power is "
                                    "<i>P</i> = &Delta;<sup>2</sup>/12.</span>")
     self.sig_tx.emit({'sender':__name__, 'data_changed':'noi'})
 def _update_noi(self):
     """ Update type + value + label for self.noi for noise"""
     self.noise = qget_cmb_box(self.cmbNoise, data=False).lower()
     self.lblNoi.setVisible(self.noise!='none')
     self.ledNoi.setVisible(self.noise!='none')
     if self.noise!='none':
         self.noi = safe_eval(self.ledNoi.text(), 0, return_type='float', sign='pos')
         self.ledNoi.setText(str(self.noi))
         if self.noise == 'gauss':
             self.lblNoi.setText(to_html("&sigma; =", frmt='bi'))
             self.ledNoi.setToolTip("<span>Standard deviation of statistical process,"
                                    "noise power is <i>P</i> = &sigma;<sup>2</sup></span>")
         elif self.noise == 'uniform':
             self.lblNoi.setText(to_html("&Delta; =", frmt='bi'))
             self.ledNoi.setToolTip("<span>Interval size for uniformly distributed process "
                                    "(e.g. quantization step size for quantization noise), "
                                    "centered around 0. Noise power is "
                                    "<i>P</i> = &Delta;<sup>2</sup>/12.</span>")
     self.sig_tx.emit({'sender':__name__, 'data_changed':'noi'})
Exemple #32
0
    def _store_entry(self, source):
        """
        When the textfield of `source` has been edited (flag `self.spec_edited` =  True),
        transform the amplitude spec back to linear unit setting and store it
        in filter dict.
        This is triggered by `QEvent.focusOut`

        Spec entries are *always* stored in linear units; only the
        displayed values are adapted to the amplitude unit, not the dictionary!
        """
        if self.spec_edited:
            unit = str(self.cmbUnitsA.currentText())
            filt_type = fb.fil[0]['ft']
            amp_label = str(source.objectName())
            amp_value = safe_eval(source.text(), fb.data_old)
            fb.fil[0].update({amp_label:unit2lin(amp_value, filt_type, amp_label, unit)})
            self.sigSpecsChanged.emit() # -> filter_specs
            self.spec_edited = False # reset flag
        self.load_dict()
Exemple #33
0
    def _update_UI(self):
        """
        Update UI when line edit field is changed (here, only the text is read
        and converted to integer) and store parameter settings in filter 
        dictionary
        """
        self.grid_density = safe_eval(self.led_remez_1.text(),
                                      self.grid_density,
                                      return_type='int',
                                      sign='pos')
        self.led_remez_1.setText(str(self.grid_density))

        if not 'wdg_fil' in fb.fil[0]:
            fb.fil[0].update({'wdg_fil': {}})
        fb.fil[0]['wdg_fil'].update(
            {'equiripple': {
                'grid_density': self.grid_density
            }})

        self.sigFiltChanged.emit()  # -> select_filter -> filter_specs
Exemple #34
0
    def _store_q_settings(self):
        """
        read out the settings of the quantization comboboxes and store them in
        filter dict. Update the fixpoint object.
        """
        fb.fil[0]['q_coeff'] = {
            'WI': abs(int(self.ledWI.text())),
            'WF': abs(int(self.ledWF.text())),
            'quant': self.cmbQQuant.currentText(),
            'ovfl': self.cmbQOvfl.currentText(),
            'frmt': self.cmbFormat.currentText(),
            'point': self.chkRadixPoint.isChecked()
        }
        self.myQ.setQobj(fb.fil[0]['q_coeff'])

        self.lblLSB.setText("{0:.{1}g}".format(self.myQ.LSB, params['FMT_ba']))
        self.lblMSB.setText("{0:.{1}g}".format(self.myQ.MSB, params['FMT_ba']))

        self.scale = safe_eval(self.ledScale.text(), self.myQ.scale)
        self.ledScale.setText(str(self.scale))
Exemple #35
0
    def setEditorData(self, editor, index):
        """
        Pass the data to be edited to the editor:
        - retrieve data with full accuracy from self.ba (in float format)
        - requantize data according to settings in fixpoint object
        - represent it in the selected format (int, hex, ...)

        editor: instance of e.g. QLineEdit
        index:  instance of QModelIndex
        """
#        data = qstr(index.data()) # get data from QTableWidget
        data_str = qstr(safe_eval(self.parent.ba[index.column()][index.row()], return_type="auto"))

        if self.parent.myQ.frmt == 'float':
            # floating point format: pass data with full resolution
            editor.setText(data_str)
        else:
            # fixpoint format with base: pass requantized data with required number of places
            editor.setText("{0:>{1}}".format(self.parent.myQ.float2frmt(data_str),
                                               self.parent.myQ.places))
Exemple #36
0
    def _load_q_settings(self):
        """
        load the quantization settings from the filter dict and set the widgets
        accordingly. Update the fixpoint object.
        """
        q_coeff = fb.fil[0]['q_coeff']
        self.ledWI.setText(str(q_coeff['WI']))
        self.ledWF.setText(str(q_coeff['WF']))
        qset_cmb_box(self.cmbQQuant, q_coeff['quant'])
        qset_cmb_box(self.cmbQOvfl, q_coeff['ovfl'])
        qset_cmb_box(self.cmbFormat, q_coeff['frmt'])
        self.chkRadixPoint.setChecked(q_coeff['point'])

        self.lblLSB.setText("{0:.{1}g}".format(self.myQ.LSB, params['FMT_ba']))
        self.lblMSB.setText("{0:.{1}g}".format(self.myQ.MSB, params['FMT_ba']))

        self.scale = safe_eval(self.ledScale.text(), self.myQ.scale)
        self.ledScale.setText(str(self.scale))

        self.myQ.setQobj(fb.fil[0]['q_coeff'])
Exemple #37
0
    def setEditorData(self, editor, index):
        """
        Pass the data to be edited to the editor:
        - retrieve data with full accuracy from self.ba (in float format)
        - requantize data according to settings in fixpoint object
        - represent it in the selected format (int, hex, ...)

        editor: instance of e.g. QLineEdit
        index:  instance of QModelIndex
        """
#        data = qstr(index.data()) # get data from QTableWidget
        data_str = qstr(safe_eval(self.parent.ba[index.column()][index.row()], return_type="auto"))

        if self.parent.myQ.frmt == 'float':
            # floating point format: pass data with full resolution
            editor.setText(data_str)
        else:
            # fixpoint format with base: pass requantized data with required number of places
            editor.setText("{0:>{1}}".format(self.parent.myQ.float2frmt(data_str),
                                               self.parent.myQ.places))
Exemple #38
0
    def _restore_gain(self, source = None):
        """
        Update QLineEdit with either full (has focus) or reduced precision (no focus)

        Called by eventFilter, _normalize_gain() and _refresh_table()
        """

        if self.ui.butEnable.isChecked():
            if len(self.zpk) == 3:
                pass
            elif len(self.zpk) == 2: # k is missing in zpk:
                self.zpk.append(1.) # use k = 1
            else:
                logger.error("P/Z list zpk has wrong length {0}".format(len(self.zpk)))

            k = safe_eval(self.zpk[2], return_type='auto')

            if not self.ui.ledGain.hasFocus():  # no focus, round the gain
                self.ui.ledGain.setText(str(params['FMT'].format(k)))
            else: # widget has focus, show gain with full precision
                self.ui.ledGain.setText(str(k))
Exemple #39
0
    def _restore_gain(self, source = None):
        """
        Update QLineEdit with either full (has focus) or reduced precision (no focus)

        Called by eventFilter, _normalize_gain() and _refresh_table()
        """

        if self.ui.butEnable.isChecked():
            if len(self.zpk) == 3:
                pass
            elif len(self.zpk) == 2: # k is missing in zpk:
                self.zpk.append(1.) # use k = 1
            else:
                logger.error("P/Z list zpk has wrong length {0}".format(len(self.zpk)))

            k = safe_eval(self.zpk[2], return_type='auto')

            if not self.ui.ledGain.hasFocus():  # no focus, round the gain
                self.ui.ledGain.setText(str(params['FMT'].format(k)))
            else: # widget has focus, show gain with full precision
                self.ui.ledGain.setText(str(k))
    def _set_filter_order(self, enb_signal=False):
        """
        Triggered when either ledOrderN or chkMinOrder are edited:
        - copy settings to fb.fil[0]
        - emit 'filt_changed' if enb_signal is True
        """
        # Determine which subwidgets are _enabled_
        if self.chkMinOrder.isVisible():
            self.ledOrderN.setEnabled(not self.chkMinOrder.isChecked())
            self.lblOrderN.setEnabled(not self.chkMinOrder.isChecked())

            if self.chkMinOrder.isChecked() == True:
                # update in case N has been changed outside this class
                self.ledOrderN.setText(str(fb.fil[0]['N']))
                fb.fil[0].update({'fo': 'min'})

            else:
                fb.fil[0].update({'fo': 'man'})

        else:
            self.lblOrderN.setEnabled(self.fo == 'man')
            self.ledOrderN.setEnabled(self.fo == 'man')

        # read manual filter order, convert to positive integer and store it
        # in filter dictionary.
        ordn = safe_eval(self.ledOrderN.text(),
                         fb.fil[0]['N'],
                         return_type='int',
                         sign='pos')
        ordn = ordn if ordn > 0 else 1
        self.ledOrderN.setText(str(ordn))
        fb.fil[0].update({'N': ordn})

        if enb_signal:
            logger.debug("Emit 'filt_changed'")
            self.sig_tx.emit({
                'sender': __name__,
                'filt_changed': 'filter_order_widget'
            })
Exemple #41
0
    def setModelData(self, editor, model, index):
        """
        When editor has finished, read the updated data from the editor,
        convert it back to floating point format and store it in both the model
        (= QTableWidget) and in self.ba. Finally, refresh the table item to 
        display it in the selected format (via `float2frmt()`).

        editor: instance of e.g. QLineEdit
        model:  instance of QAbstractTableModel
        index:  instance of QModelIndex
        """

        # check for different editor environments if needed and provide a default:
        #        if isinstance(editor, QtGui.QTextEdit):
        #            model.setData(index, editor.toPlainText())
        #        elif isinstance(editor, QComboBox):
        #            model.setData(index, editor.currentText())
        #        else:
        #            super(ItemDelegate, self).setModelData(editor, model, index)
        if self.parent.myQ.frmt == 'float':
            data = safe_eval(
                qstr(editor.text()),
                self.parent.ba[index.column()][index.row()],
                return_type='auto')  # raw data without fixpoint formatting
        else:
            data = self.parent.myQ.frmt2float(
                qstr(editor.text()),
                self.parent.myQ.frmt)  # transform back to float

        model.setData(index, data)  # store in QTableWidget
        # if the entry is complex, convert ba (list of arrays) to complex type
        if isinstance(data, complex):
            self.parent.ba[0] = self.parent.ba[0].astype(complex)
            self.parent.ba[1] = self.parent.ba[1].astype(complex)
        self.parent.ba[index.column()][index.row()] = data  # store in self.ba
        qstyle_widget(self.parent.ui.butSave, 'changed')
        self.parent._refresh_table_item(index.row(),
                                        index.column())  # refresh table entry
Exemple #42
0
    def displayText(self, text, locale):
        """
        Display `text` with selected fixpoint base and number of places

        text:   string / QVariant from QTableWidget to be rendered
        locale: locale for the text

        The instance parameter myQ.ovr_flag is set to +1 or -1 for positive /
        negative overflows, else it is 0.
        """
        data_str = qstr(text) # convert to "normal" string

        if self.parent.myQ.frmt == 'float':
            data = safe_eval(data_str, return_type='auto') # convert to float
            return "{0:.{1}g}".format(data, params['FMT_ba'])

        elif self.parent.myQ.frmt == 'dec' and self.parent.myQ.WF > 0:
            # decimal fixpoint representation with fractional part
            return "{0:.{1}g}".format(self.parent.myQ.float2frmt(data_str),
                                        params['FMT_ba'])
        else:
            return "{0:>{1}}".format(self.parent.myQ.float2frmt(data_str),
                                        self.parent.myQ.places)
Exemple #43
0
 def _update_amp1(self):
     """ Update value for self.A1 from QLineEditWidget"""
     self.A1 = safe_eval(self.ledAmp1.text(), self.A1, return_type='float')
     self.ledAmp1.setText(str(self.A1))
     self.sig_tx.emit({'sender': __name__, 'data_changed': 'a1'})
Exemple #44
0
 def _update_amp2(self):
     """ Update value for self.A2 from the QLineEditWidget"""
     self.A2 = safe_eval(self.ledAmp2.text(), self.A2, return_type='float')
     self.ledAmp2.setText(str(self.A2))
     self.sig_tx.emit({'sender': __name__, 'data_changed': 'a2'})
 def displayText(self, text, locale):
     return "{:.{n_digits}g}".format(safe_eval(qstr(text),
                                               return_type='cmplx'),
                                     n_digits=params['FMT_pz'])
Exemple #46
0
 def _update_DC(self):
     """ Update value for self.DC from the QLineEditWidget"""
     self.DC = safe_eval(self.ledDC.text(), 0, return_type='float')
     self.ledDC.setText(str(self.DC))
     self.sig_tx.emit({'sender': __name__, 'data_changed': 'dc'})
Exemple #47
0
 def _store_entry(source):
     if self.spec_edited:
         self.stim_freq = safe_eval(source.text()) / fb.fil[0]['f_S']
         self.spec_edited = False  # reset flag
         self.draw()
Exemple #48
0
    def draw_impz(self):
        """
        (Re-)calculate h[n] and draw the figure
        """
        log = self.chkLog.isChecked()
        stim = str(self.cmbStimulus.currentText())
        periodic_sig = stim in {"Cos", "Sine", "Rect", "Saw"}
        self.lblLogBottom.setVisible(log)
        self.ledLogBottom.setVisible(log)
        self.lbldB.setVisible(log)

        self.lblFreq.setVisible(periodic_sig)
        self.ledFreq.setVisible(periodic_sig)
        self.lblFreqUnit.setVisible(periodic_sig)

        self.lblFreqUnit.setText(rt_label(fb.fil[0]['freq_specs_unit']))
        self.load_dict()

        self.bb = np.asarray(fb.fil[0]['ba'][0])
        self.aa = np.asarray(fb.fil[0]['ba'][1])
        if min(len(self.aa), len(self.bb)) < 2:
            logger.error('No proper filter coefficients: len(a), len(b) < 2 !')
            return

        sos = np.asarray(fb.fil[0]['sos'])
        antiCausal = 'zpkA' in fb.fil[0]
        causal = not (antiCausal)

        self.f_S = fb.fil[0]['f_S']

        N_entry = safe_eval(self.ledNPoints.text(),
                            0,
                            return_type='int',
                            sign='pos')
        N = self.calc_n_points(N_entry)
        if N_entry != 0:  # automatic calculation
            self.ledNPoints.setText(str(N))

        self.A = safe_eval(self.ledAmp.text(), self.A, return_type='float')
        self.ledAmp.setText(str(self.A))

        t = np.linspace(0, N / self.f_S, N, endpoint=False)

        title_str = r'Impulse Response'  # default
        H_str = r'$h[n]$'  # default

        # calculate h[n]
        if stim == "Pulse":
            x = np.zeros(N)
            x[0] = self.A  # create dirac impulse as input signal
        elif stim == "Step":
            x = self.A * np.ones(N)  # create step function
            title_str = r'Step Response'
            H_str = r'$h_{\epsilon}[n]$'
        elif stim == "StepErr":
            x = self.A * np.ones(N)  # create step function
            title_str = r'Settling Error'
            H_str = r'$h_{\epsilon, \infty} - h_{\epsilon}[n]$'

        elif stim in {"Cos"}:
            x = self.A * np.cos(2 * np.pi * t * float(self.ledFreq.text()))
            if stim == "Cos":
                title_str = r'Transient Response to Cosine Signal'
                H_str = r'$y_{\cos}[n]$'

        elif stim in {"Sine", "Rect"}:
            x = self.A * np.sin(2 * np.pi * t * float(self.ledFreq.text()))
            if stim == "Sine":
                title_str = r'Transient Response to Sine Signal'
                H_str = r'$y_{\sin}[n]$'
            else:
                x = self.A * np.sign(x)
                title_str = r'Transient Response to Rect. Signal'
                H_str = r'$y_{rect}[n]$'

        elif stim == "Saw":
            x = self.A * sig.sawtooth(t *
                                      (float(self.ledFreq.text()) * 2 * np.pi))
            title_str = r'Transient Response to Sawtooth Signal'
            H_str = r'$y_{saw}[n]$'

        elif stim == "RandN":
            x = self.A * np.random.randn(N)
            title_str = r'Transient Response to Gaussian Noise'
            H_str = r'$y_{gauss}[n]$'

        elif stim == "RandU":
            x = self.A * (np.random.rand(N) - 0.5)
            title_str = r'Transient Response to Uniform Noise'
            H_str = r'$y_{uni}[n]$'

        else:
            logger.error('Unknown stimulus "{0}"'.format(stim))
            return

        if len(sos) > 0 and (
                causal):  # has second order sections and is causal
            h = sig.sosfilt(sos, x)
        elif (antiCausal):
            h = sig.filtfilt(self.bb, self.aa, x, -1, None)
        else:  # no second order sections or antiCausals for current filter
            h = sig.lfilter(self.bb, self.aa, x)

        dc = sig.freqz(self.bb, self.aa, [0])

        if stim == "StepErr":
            h = h - abs(dc[1])  # subtract DC value from response

        h = np.real_if_close(
            h, tol=1e3)  # tol specified in multiples of machine eps
        self.cmplx = np.any(np.iscomplex(h))
        if self.cmplx:
            h_i = h.imag
            h = h.real
            H_i_str = r'$\Im\{$' + H_str + '$\}$'
            H_str = r'$\Re\{$' + H_str + '$\}$'
        if log:
            self.bottom = safe_eval(self.ledLogBottom.text(),
                                    self.bottom,
                                    return_type='float')
            self.ledLogBottom.setText(str(self.bottom))
            H_str = r'$|$ ' + H_str + '$|$ in dB'
            h = np.maximum(20 * np.log10(abs(h)), self.bottom)
            if self.cmplx:
                h_i = np.maximum(20 * np.log10(abs(h_i)), self.bottom)
                H_i_str = r'$\log$ ' + H_i_str + ' in dB'
        else:
            self.bottom = 0

        self.init_axes()

        #================ Main Plotting Routine =========================
        [ml, sl, bl] = self.ax_r.stem(t,
                                      h,
                                      bottom=self.bottom,
                                      markerfmt='o',
                                      label='$h[n]$')
        stem_fmt = params['mpl_stimuli']
        if self.chkPltStim.isChecked():
            [ms, ss, bs] = self.ax_r.stem(t,
                                          x,
                                          bottom=self.bottom,
                                          label='Stim.',
                                          **stem_fmt)
            ms.set_mfc(stem_fmt['mfc'])
            ms.set_mec(stem_fmt['mec'])
            ms.set_ms(stem_fmt['ms'])
            ms.set_alpha(stem_fmt['alpha'])
            for stem in ss:
                stem.set_linewidth(stem_fmt['lw'])
                stem.set_color(stem_fmt['mec'])
                stem.set_alpha(stem_fmt['alpha'])
            bs.set_visible(False)  # invisible bottomline
        expand_lim(self.ax_r, 0.02)
        self.ax_r.set_title(title_str)

        if self.cmplx:
            [ml_i, sl_i, bl_i] = self.ax_i.stem(t,
                                                h_i,
                                                bottom=self.bottom,
                                                markerfmt='d',
                                                label='$h_i[n]$')
            self.ax_i.set_xlabel(fb.fil[0]['plt_tLabel'])
            # self.ax_r.get_xaxis().set_ticklabels([]) # removes both xticklabels
            # plt.setp(ax_r.get_xticklabels(), visible=False)
            # is shorter but imports matplotlib, set property directly instead:
            [label.set_visible(False) for label in self.ax_r.get_xticklabels()]
            self.ax_r.set_ylabel(H_str + r'$\rightarrow $')
            self.ax_i.set_ylabel(H_i_str + r'$\rightarrow $')
        else:
            self.ax_r.set_xlabel(fb.fil[0]['plt_tLabel'])
            self.ax_r.set_ylabel(H_str + r'$\rightarrow $')

        if self.ACTIVE_3D:  # not implemented / tested yet

            # plotting the stems
            for i in range(len(t)):
                self.ax3d.plot([t[i], t[i]], [h[i], h[i]], [0, h_i[i]],
                               '-',
                               linewidth=2,
                               alpha=.5)

            # plotting a circle on the top of each stem
            self.ax3d.plot(t,
                           h,
                           h_i,
                           'o',
                           markersize=8,
                           markerfacecolor='none',
                           label='$h[n]$')

            self.ax3d.set_xlabel('x')
            self.ax3d.set_ylabel('y')
            self.ax3d.set_zlabel('z')

        self.redraw()
Exemple #49
0
 def _set_eps(self):
     """
     Set tolerance value 
     """
     self.ui.eps = safe_eval(self.ui.ledEps.text(), alt_expr=self.ui.eps, sign='pos')
     self.ui.ledEps.setText(str(self.ui.eps))
Exemple #50
0
        def _update_param1():
            self.ledWinPar1.setToolTip(tooltip)
            self.lblWinPar1.setText(to_html(txt_par1, frmt='bi'))

            self.param1 = safe_eval(self.ledWinPar1.text(), self.param1, return_type='float', sign='pos')
            self.ledWinPar1.setText(str(self.param1))
Exemple #51
0
 def displayText(self, text, locale):
     if not isinstance(text, six.text_type):  #
         text = text.toString(
         )  # needed for Python 2, doesn't work with Py3
     return "{:.{n_digits}g}".format(safe_eval(text),
                                     n_digits=params['FMT_pz'])
Exemple #52
0
 def _store_entry(source):
     if self.spec_edited:
         self.stim_freq = safe_eval(source.text(), self.stim_freq * fb.fil[0]['f_S'],
                                     return_type='float') / fb.fil[0]['f_S']
         self.spec_edited = False # reset flag
         self.draw()
        def _update_param1():
            self.ledWinPar1.setToolTip(tooltip)
            self.lblWinPar1.setText(to_html(txt_par1, frmt='bi'))

            self.param1 = safe_eval(self.ledWinPar1.text(), self.param1, return_type='float', sign='pos')
            self.ledWinPar1.setText(str(self.param1))