Beispiel #1
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
    def ui2dict(self):
        """ 
        Update the attributes `self.WI`, `self.WF` and `self.W` and `self.q_dict`
        when one of the QLineEdit widgets has been edited.
        
        Emit a signal with `{'ui':objectName of the sender}`.
        """

        self.WI = int(
            safe_eval(self.ledWI.text(),
                      self.WI,
                      return_type="int",
                      sign='pos'))
        self.ledWI.setText(qstr(self.WI))
        self.WF = int(
            safe_eval(self.ledWF.text(),
                      self.WF,
                      return_type="int",
                      sign='pos'))
        self.ledWF.setText(qstr(self.WF))
        self.W = int(self.WI + self.WF + 1)

        self.q_dict.update({'WI': self.WI, 'WF': self.WF, 'W': self.W})

        if self.sender():
            name = self.sender().objectName()
            logger.debug("sender: {0}".format(name))
            dict_sig = {'sender': __name__, 'ui': name}
            self.sig_tx.emit(dict_sig)
        else:
            logger.error("sender without name, shouldn't happen!")
    def dict2ui(self, q_dict=None):
        """ 
        Update the widgets `WI` and `WF` and the corresponding attributes
        from the dict passed as the argument
        """
        if q_dict is None:
            q_dict = self.q_dict

        if 'WI' in q_dict:
            self.WI = safe_eval(q_dict['WI'],
                                self.WI,
                                return_type="int",
                                sign='pos')
            self.ledWI.setText(qstr(self.WI))
        else:
            logger.warning("No key 'WI' in dict!")

        if 'WF' in q_dict:
            self.WF = safe_eval(q_dict['WF'],
                                self.WF,
                                return_type="int",
                                sign='pos')
            self.ledWF.setText(qstr(self.WF))
        else:
            logger.warning("No key 'WF' in dict!")

        self.W = self.WF + self.WI + 1
Beispiel #4
0
    def ui2dict(self):  # was: save_ui
        """ 
        Update the attributes `self.WI`, `self.WF` and `self.W` when one of the QLineEdit
        widgets has been edited.
        
        Return a dict with the three parameters when called directly, cast values
        to standard python int format (instead of e.g. np.int64) to avoid problems 
        with HDL simulators downstream
        """
        self.WI = int(
            safe_eval(self.ledWI.text(),
                      self.WI,
                      return_type="int",
                      sign='pos'))
        self.ledWI.setText(qstr(self.WI))
        self.WF = int(
            safe_eval(self.ledWF.text(),
                      self.WF,
                      return_type="int",
                      sign='pos'))
        self.ledWF.setText(qstr(self.WF))
        self.W = int(self.WI + self.WF + 1)

        self.q_dict.update({'WI': self.WI, 'WF': self.WF, 'W': self.W})

        dict_sig = {'sender': __name__, 'fixp_changed': ''}
        self.sig_tx.emit(dict_sig)
Beispiel #5
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
Beispiel #6
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()
    def exportHDL(self):
        """
        Synthesize HDL description of filter
        """
        dlg = QFD(self)  # instantiate file dialog object

        file_types = "Verilog (*.v)"

        hdl_file, hdl_filter = dlg.getSaveFileName_(caption="Save HDL as",
                                                    directory=dirs.save_dir,
                                                    filter=file_types)
        hdl_file = qstr(hdl_file)

        if hdl_file != "":  # "operation cancelled" returns an empty string
            # return '.v' or '.vhd' depending on filetype selection:
            hdl_type = extract_file_ext(qstr(hdl_filter))[0]
            # sanitized dir + filename + suffix. The filename suffix is replaced
            # by `v` later.
            hdl_file = os.path.normpath(hdl_file)
            hdl_dir_name = os.path.dirname(
                hdl_file)  # extract the directory path
            if not os.path.isdir(
                    hdl_dir_name):  # create directory if it doesn't exist
                os.mkdir(hdl_dir_name)
            dirs.save_dir = hdl_dir_name  # make this directory the new default / base dir
            hdl_file_name = os.path.join(
                hdl_dir_name,
                os.path.splitext(os.path.basename(hdl_file))[0] + ".v")

            # =============================================================================
            #             # remove the suffix from the filename:
            #
            #             if hdl_type == '.vhd':
            #                 hdl = 'VHDL'
            #             elif hdl_type == '.v':
            #                 hdl = 'Verilog'
            #             else:
            #                 logger.error('Unknown file extension "{0}", cancelling.'.format(hdl_type))
            #                 return
            #
            # =============================================================================
            logger.info('Creating hdl_file "{0}"'.format(
                os.path.join(hdl_dir_name, hdl_file_name)))
            try:
                self.update_fxqc_dict()
                self.fx_wdg_inst.construct_hdlfilter(self.fxqc_dict)
                code = self.fx_wdg_inst.to_verilog(self.fxqc_dict)

                logger.info(str(code))

                with io.open(hdl_file_name, 'w', encoding="utf8") as f:
                    f.write(str(code))

                logger.info("HDL conversion finished!")
            except (IOError, TypeError) as e:
                logger.warning(e)
Beispiel #8
0
 def ui2dict(self):
     """ 
     Update the attributes `self.WI` and `self.WF` and the filter dict 
     when one of the QLineEdit widgets has been edited.
     """
     self.WI = safe_eval(self.ledWI.text(), self.WI, return_type="int", sign='pos')
     self.ledWI.setText(qstr(self.WI))
     self.WF = safe_eval(self.ledWF.text(), self.WF, return_type="int", sign='pos')
     self.ledWF.setText(qstr(self.WF))
     fb.fil[0]["q_coeff"].update({'WI':self.WI, 'WF':self.WF})
     self.W = self.WI + self.WF + 1
Beispiel #9
0
 def ui2dict(self): # was: save_ui
     """ 
     Update the attributes `self.WI`, `self.WF` and `self.W` when one of the QLineEdit
     widgets has been edited.
     
     Return a dict with the three parameters when called directly
     """
     self.WI = safe_eval(self.ledWI.text(), self.WI, return_type="int", sign='pos')
     self.ledWI.setText(qstr(self.WI))
     self.WF = safe_eval(self.ledWF.text(), self.WF, return_type="int", sign='pos')
     self.ledWF.setText(qstr(self.WF))
     self.W = self.WI + self.WF + 1
     return {'WI':self.WI, 'WF':self.WF, 'W':self.W}
Beispiel #10
0
    def exportHDL(self):
        """
        Synthesize HDL description of filter using myHDL module
        """
        dlg = QFD(self)  # instantiate file dialog object

        file_types = "Verilog (*.v);;VHDL (*.vhd)"

        hdl_file, hdl_filter = dlg.getSaveFileName_(caption="Save HDL as",
                                                    directory=dirs.save_dir,
                                                    filter=file_types)
        hdl_file = qstr(hdl_file)

        if hdl_file != "":  # "operation cancelled" returns an empty string
            # return '.v' or '.vhd' depending on filetype selection:
            hdl_type = extract_file_ext(qstr(hdl_filter))[0]
            # sanitized dir + filename + suffix. The filename suffix is replaced
            # by `hdl_type` later.
            hdl_file = os.path.normpath(hdl_file)
            hdl_dir_name = os.path.dirname(
                hdl_file)  # extract the directory path
            if not os.path.isdir(
                    hdl_dir_name):  # create directory if it doesn't exist
                os.mkdir(hdl_dir_name)
            dirs.save_dir = hdl_dir_name  # make this directory the new default / base dir

            # remove the suffix from the filename:
            hdl_file_name = os.path.splitext(os.path.basename(hdl_file))[0]

            if hdl_type == '.vhd':
                hdl = 'VHDL'
            elif hdl_type == '.v':
                hdl = 'Verilog'
            else:
                logger.error(
                    'Unknown file extension "{0}", cancelling.'.format(
                        hdl_type))
                return

            logger.info('Creating hdl_file "{0}"'.format(
                os.path.join(hdl_dir_name, hdl_file_name + hdl_type)))
            try:
                self.update_fxqc_dict()
                self.hdl_filter_inst.setup(self.fxqc_dict)
                self.hdl_filter_inst.convert(hdl=hdl,
                                             name=hdl_file_name,
                                             path=hdl_dir_name)

                logger.info("HDL conversion finished!")
            except (IOError, TypeError) as e:
                logger.warning(e)
Beispiel #11
0
    def dict2ui(self, w_dict):
        """ 
        Update the widgets `WI` and `WF` from the dict passed as the argument
        """
        if 'WI' in w_dict:
            self.WI = safe_eval(w_dict['WI'], self.WI, return_type="int", sign='pos')
            self.ledWI.setText(qstr(self.WI))
        else:
            logger.warning("No key 'WI' in dict!")

        if 'WF' in w_dict:
            self.WF = safe_eval(w_dict['WF'], self.WF, return_type="int", sign='pos')
            self.ledWF.setText(qstr(self.WF))
        else:
            logger.warning("No key 'WF' in dict!")
Beispiel #12
0
    def setModelData(self, editor, model, index):
        """
        When editor has finished, read the updated data from the editor,
        convert it to complex format and store it in both the model
        (= QTableWidget) and in `zpk`. Finally, refresh the table item to
        display it in the selected format (via `to be defined`) and normalize
        the gain.

        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)

        # convert entered string to complex, pass the old value as default
        data = self.parent.frmt2cmplx(
            qstr(editor.text()), self.parent.zpk[index.column()][index.row()])
        model.setData(index, data)  # store in QTableWidget
        self.parent.zpk[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
        self.parent._normalize_gain()  # recalculate gain
Beispiel #13
0
    def setModelData(self, editor, model, index):
        """
        When editor has finished, read the updated data from the editor,
        convert it to complex format and store it in both the model
        (= QTableWidget) and in `zpk`. Finally, refresh the table item to
        display it in the selected format (via `to be defined`) and normalize
        the gain.

        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)

        # convert entered string to complex, pass the old value as default
        data = self.parent.frmt2cmplx(qstr(editor.text()), 
                                      self.parent.zpk[index.column()][index.row()])
        model.setData(index, data)                          # store in QTableWidget
        self.parent.zpk[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
        self.parent._normalize_gain() # recalculate gain
Beispiel #14
0
    def dict2ui(self, c_dict=None):
        """ 
        Update the ui and the attributes `self.WI` and `self.WF` from the filter
        dict. `dict2ui()` has to be called when the coefficients or the word
        format has been changed outside the class, e.g. by a new filter design or
        by changing the coefficient format in `input_coeffs.py`.
        """
        if not c_dict:
            c_dict = fb.fil[0]['q_coeff']
        self.WI = c_dict['WI']
        self.WF = c_dict['WF']
        self.ledWI.setText(qstr(self.WI))
        self.ledWF.setText(qstr(self.WF))
        self.W = self.WI + self.WF + 1

        self.c_dict = build_coeff_dict()
Beispiel #15
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()
Beispiel #16
0
    def exportHDL(self):
        """
        Synthesize HDL description of filter using myHDL module
        """
        dlg = QFD(self) # instantiate file dialog object

        file_types = "Verilog (*.v);;VHDL (*.vhd)"

        hdl_file, hdl_filter = dlg.getSaveFileName_(
                caption="Save HDL as", directory=dirs.save_dir,
                filter=file_types)
        hdl_file = qstr(hdl_file)

        if hdl_file != "": # "operation cancelled" returns an empty string
            # return '.v' or '.vhd' depending on filetype selection:
            hdl_type = extract_file_ext(qstr(hdl_filter))[0]
            # sanitized dir + filename + suffix. The filename suffix is replaced
            # by `hdl_type` later.
            hdl_file = os.path.normpath(hdl_file)
            hdl_dir_name = os.path.dirname(hdl_file) # extract the directory path
            if not os.path.isdir(hdl_dir_name): # create directory if it doesn't exist
                os.mkdir(hdl_dir_name)
            dirs.save_dir = hdl_dir_name # make this directory the new default / base dir

            # remove the suffix from the filename:
            hdl_file_name = os.path.splitext(os.path.basename(hdl_file))[0]

            if hdl_type == '.vhd':
                hdl = 'VHDL'
            elif hdl_type == '.v':
                hdl = 'Verilog'
            else:
                logger.error('Unknown file extension "{0}", cancelling.'.format(hdl_type))
                return

            logger.info('Creating hdl_file "{0}"'.format(
                        os.path.join(hdl_dir_name, hdl_file_name + hdl_type)))
            try:
                self.update_fxqc_dict()
                self.hdl_filter_inst.setup(self.fxqc_dict)
                self.hdl_filter_inst.convert(hdl=hdl, name=hdl_file_name, path=hdl_dir_name)

                logger.info("HDL conversion finished!")
            except (IOError, TypeError) as e:
                logger.warning(e)
Beispiel #17
0
    def _load_q_settings(self):
        """
        load the quantization settings from the filter dict and set the widgets
        accordingly. Update the fixpoint object.
        """
        self.myQ.setQobj(fb.fil[0]['q_coeff'])
        q_coeff = self.myQ.q_obj

        self.ui.ledWI.setText(qstr(q_coeff['WI']))
        self.ui.ledWF.setText(qstr(q_coeff['WF']))
        qset_cmb_box(self.ui.cmbQuant, q_coeff['quant'])
        qset_cmb_box(self.ui.cmbQOvfl,  q_coeff['ovfl'])
        qset_cmb_box(self.ui.cmbFormat, q_coeff['frmt'])
        self.ui.ledScale.setText(qstr(q_coeff['scale']))

        self.ui.ledW.setText(qstr(self.myQ.W))
        self.ui.lblLSB.setText("{0:.{1}g}".format(self.myQ.LSB, params['FMT_ba']))
        self.ui.lblMSB.setText("{0:.{1}g}".format(self.myQ.MSB, params['FMT_ba']))
        self.ui.lblMAX.setText("{0}".format(self.myQ.float2frmt(self.myQ.MAX/self.myQ.scale)))
Beispiel #18
0
    def _load_q_settings(self):
        """
        load the quantization settings from the filter dict and set the widgets
        accordingly. Update the fixpoint object.
        """
        self.myQ.setQobj(fb.fil[0]['q_coeff'])
        q_coeff = self.myQ.q_obj

        self.ui.ledWI.setText(qstr(q_coeff['WI']))
        self.ui.ledWF.setText(qstr(q_coeff['WF']))
        qset_cmb_box(self.ui.cmbQuant, q_coeff['quant'])
        qset_cmb_box(self.ui.cmbQOvfl,  q_coeff['ovfl'])
        qset_cmb_box(self.ui.cmbFormat, q_coeff['frmt'])
        self.ui.ledScale.setText(qstr(q_coeff['scale']))

        self.ui.ledW.setText(qstr(self.myQ.W))
        self.ui.lblLSB.setText("{0:.{1}g}".format(self.myQ.LSB, params['FMT_ba']))
        self.ui.lblMSB.setText("{0:.{1}g}".format(self.myQ.MSB, params['FMT_ba']))
        self.ui.lblMAX.setText("{0}".format(self.myQ.float2frmt(self.myQ.MAX/self.myQ.scale)))
Beispiel #19
0
    def ui2qdict(self):
        """
        Read out the settings of the quantization comboboxes.

        - Store them in the filter dict `fb.fil[0]['fxqc']['QCB']` and as class
            attributes in the fixpoint object `self.myQ`

        - Emit a signal with `'view_changed':'q_coeff'`

        - Refresh the table
        """
        fb.fil[0]['fxqc']['QCB'] = {
            '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'),
            'W':
            safe_eval(self.ui.ledW.text(),
                      self.myQ.W,
                      return_type='int',
                      sign='pos'),
            'quant':
            qstr(self.ui.cmbQuant.currentText()),
            'ovfl':
            qstr(self.ui.cmbQOvfl.currentText()),
            'frmt':
            qstr(self.ui.cmbFormat.currentText().lower()),
            'scale':
            qstr(self.ui.ledScale.text())
        }

        self.myQ.setQobj(fb.fil[0]['fxqc']['QCB'])  # update fixpoint object

        self.sig_tx.emit({'sender': __name__, 'view_changed': 'q_coeff'})

        self._update_MSB_LSB()

        self._refresh_table()
Beispiel #20
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))
Beispiel #21
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))
Beispiel #22
0
 def ui2dict(self):
     """ 
     Update the attributes `self.WI` and `self.WF` and the filter dict 
     when one of the QLineEdit widgets has been edited.
    
     Cast values to standard python int format (instead of e.g. np.int64) 
     to avoid problems with HDL simulators downstream
     """
     self.WI = int(
         safe_eval(self.ledWI.text(),
                   self.WI,
                   return_type="int",
                   sign='pos'))
     self.ledWI.setText(qstr(self.WI))
     self.WF = int(
         safe_eval(self.ledWF.text(),
                   self.WF,
                   return_type="int",
                   sign='pos'))
     self.ledWF.setText(qstr(self.WF))
     fb.fil[0]["q_coeff"].update({'WI': self.WI, 'WF': self.WF})
     self.W = int(self.WI + self.WF + 1)
Beispiel #23
0
    def qdict2ui(self):
        """
        Set the UI from the quantization dict and update the fixpoint object.
        When neither WI == 0 nor WF == 0, set the quantization format to general
        fractional format qfrac.
        """
        self.ui.ledWI.setText(qstr(fb.fil[0]['fxqc']['QCB']['WI']))
        self.ui.ledWF.setText(qstr(fb.fil[0]['fxqc']['QCB']['WF']))
        self.ui.ledW.setText(qstr(fb.fil[0]['fxqc']['QCB']['W']))
        if fb.fil[0]['fxqc']['QCB']['WI'] != 0 and fb.fil[0]['fxqc']['QCB'][
                'WF'] != 0:
            qset_cmb_box(self.ui.cmbQFrmt, 'qfrac', data=True)

        self.ui.ledScale.setText(qstr(fb.fil[0]['fxqc']['QCB']['scale']))
        qset_cmb_box(self.ui.cmbQuant, fb.fil[0]['fxqc']['QCB']['quant'])
        qset_cmb_box(self.ui.cmbQOvfl, fb.fil[0]['fxqc']['QCB']['ovfl'])

        self.myQ.setQobj(fb.fil[0]['fxqc']['QCB'])  # update class attributes

        self._set_number_format(
        )  # quant format has been changed, update display
        self._update_MSB_LSB()
Beispiel #24
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
Beispiel #25
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))
Beispiel #26
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))
Beispiel #27
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
Beispiel #28
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)
Beispiel #29
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)
Beispiel #30
0
    def fixp(self, y, scaling='mult'):
        """
        Return fixed-point integer or fractional representation for `y`
        (scalar or array-like) with the same shape as `y`.

        Saturation / two's complement wrapping happens outside the range +/- MSB,
        requantization (round, floor, fix, ...) is applied on the ratio `y / LSB`.

        Parameters
        ----------
        y: scalar or array-like object
            input value (floating point format) to be quantized

        scaling: String
            Determine the scaling before and after quantizing / saturation

            *'mult'* float in, int out:
                `y` is multiplied by `self.scale` *before* quantizing / saturating
            **'div'**: int in, float out:
                `y` is divided by `self.scale` *after* quantizing / saturating.
            **'multdiv'**: float in, float out (default):
                both of the above

            For all other settings, `y` is transformed unscaled.

        Returns
        -------
        float scalar or ndarray
            with the same shape as `y`, in the range
            `-2*self.MSB` ... `2*self.MSB-self.LSB`

        Examples
        --------

        >>> q_obj_a = {'WI':1, 'WF':6, 'ovfl':'sat', 'quant':'round'}
        >>> myQa = Fixed(q_obj_a) # instantiate fixed-point object myQa
        >>> myQa.resetN()  # reset overflow counter
        >>> a = np.arange(0,5, 0.05) # create input signal

        >>> aq = myQa.fixed(a) # quantize input signal
        >>> plt.plot(a, aq) # plot quantized vs. original signal
        >>> print(myQa.N_over, "overflows!") # print number of overflows

        >>> # Convert output to same format as input:
        >>> b = np.arange(200, dtype = np.int16)
        >>> btype = np.result_type(b)
        >>> # MSB = 2**7, LSB = 2**(-2):
        >>> q_obj_b = {'WI':7, 'WF':2, 'ovfl':'wrap', 'quant':'round'}
        >>> myQb = Fixed(q_obj_b) # instantiate fixed-point object myQb
        >>> bq = myQb.fixed(b)
        >>> bq = bq.astype(btype) # restore original variable type
        """

        #======================================================================
        # (1) : INITIALIZATION
        #       Convert input argument into proper floating point scalars /
        #       arrays and initialize flags
        #======================================================================
        scaling = scaling.lower()
        if np.shape(y):
            # Input is an array:
            #   Create empty arrays for result and overflows with same shape as y
            #   for speedup, test for invalid types
            SCALAR = False
            y = np.asarray(y)  # convert lists / tuples / ... to numpy arrays
            yq = np.zeros(y.shape)
            over_pos = over_neg = np.zeros(y.shape, dtype=bool)
            self.ovr_flag = np.zeros(y.shape, dtype=int)

            if np.issubdtype(y.dtype, np.number):
                pass
            elif y.dtype.kind in {'U', 'S'}:  # string or unicode
                try:
                    y = y.astype(np.float64)  # try to convert to float
                except (TypeError, ValueError):
                    try:
                        np.char.replace(y, ' ', '')  # remove all whitespace
                        y = y.astype(complex)  # try to convert to complex
                    except (TypeError, ValueError
                            ) as e:  # try converting elements recursively
                        y = list(
                            map(
                                lambda y_scalar: self.fixp(y_scalar,
                                                           scaling=scaling),
                                y))
            else:
                logger.error("Argument '{0}' is of type '{1}',\n"
                             "cannot convert to float.".format(y, y.dtype))
                y = np.zeros(y.shape)
        else:
            # Input is a scalar
            SCALAR = True
            # get rid of errors that have occurred upstream
            if y is None or str(y) == "":
                y = 0
            # If y is not a number, remove whitespace and try to convert to
            # to float and or to complex format:
            elif not np.issubdtype(type(y), np.number):
                y = qstr(y)
                y = y.replace(' ', '')  # remove all whitespace
                try:
                    y = float(y)
                except (TypeError, ValueError):
                    try:
                        y = complex(y)
                    except (TypeError, ValueError) as e:
                        logger.error("Argument '{0}' yields \n {1}".format(
                            y, e))
                        y = 0.0
            over_pos = over_neg = yq = 0
            self.ovr_flag = 0

        # convert pseudo-complex (imag = 0) and complex values to real
        y = np.real_if_close(y)
        if np.iscomplexobj(y):
            logger.warning(
                "Casting complex values to real before quantization!")
            # quantizing complex objects is not supported yet
            y = y.real

        y_in = y  # y before scaling / quantizing
        #======================================================================
        # (2) : INPUT SCALING
        #       Multiply by `scale` factor before requantization and saturation
        #       when `scaling=='mult'`or 'multdiv'
        #======================================================================
        if scaling in {'mult', 'multdiv'}:
            y = y * self.scale

        #======================================================================
        # (3) : QUANTIZATION
        #       Divide by LSB to obtain an intermediate format where the
        #       quantization step size = 1.
        #       Next, apply selected quantization method to convert
        #       floating point inputs to "fixpoint integers".
        #       Finally, multiply by LSB to restore original scale.
        #=====================================================================
        y = y / self.LSB

        if self.quant == 'floor':
            yq = np.floor(y)
            # largest integer i, such that i <= x (= binary truncation)
        elif self.quant == 'round':
            yq = np.round(y)
            # rounding, also = binary rounding
        elif self.quant == 'fix':
            yq = np.fix(y)
            # round to nearest integer towards zero ("Betragsschneiden")
        elif self.quant == 'ceil':
            yq = np.ceil(y)
            # smallest integer i, such that i >= x
        elif self.quant == 'rint':
            yq = np.rint(y)
            # round towards nearest int
        elif self.quant == 'none':
            yq = y
            # return unquantized value
        else:
            raise Exception('Unknown Requantization type "%s"!' % (self.quant))

        yq = yq * self.LSB
        logger.debug("y_in={0} | y={1} | yq={2}".format(y_in, y, yq))

        #======================================================================
        # (4) : Handle Overflow / saturation w.r.t. to the MSB, returning a
        #       result in the range MIN = -2*MSB ... + 2*MSB-LSB = MAX
        #=====================================================================
        if self.ovfl == 'none':
            pass
        else:
            # Bool. vectors with '1' for every neg./pos overflow:
            over_neg = (yq < self.MIN)
            over_pos = (yq > self.MAX)
            # create flag / array of flags for pos. / neg. overflows
            self.ovr_flag = over_pos.astype(int) - over_neg.astype(int)
            # No. of pos. / neg. / all overflows occured since last reset:
            self.N_over_neg += np.sum(over_neg)
            self.N_over_pos += np.sum(over_pos)
            self.N_over = self.N_over_neg + self.N_over_pos

            # Replace overflows with Min/Max-Values (saturation):
            if self.ovfl == 'sat':
                yq = np.where(over_pos, self.MAX, yq)  # (cond, true, false)
                yq = np.where(over_neg, self.MIN, yq)
            # Replace overflows by two's complement wraparound (wrap)
            elif self.ovfl == 'wrap':
                yq = np.where(
                    over_pos | over_neg, yq - 4. * self.MSB * np.fix(
                        (np.sign(yq) * 2 * self.MSB + yq) / (4 * self.MSB)),
                    yq)
            else:
                raise Exception('Unknown overflow type "%s"!' % (self.ovfl))
                return None
        #======================================================================
        # (5) : OUTPUT SCALING
        #       Divide result by `scale` factor when `scaling=='div'`or 'multdiv'
        #       to obtain correct scaling for floats
        #       - frmt2float() always returns float
        #       - input_coeffs when quantizing the coefficients
        #       float2frmt passes on the scaling argument
        #======================================================================

        if scaling in {'div', 'multdiv'}:
            yq = yq / self.scale

        if SCALAR and isinstance(yq, np.ndarray):
            yq = yq.item()  # convert singleton array to scalar

        return yq
Beispiel #31
0
 def text(self, item):
     """
     Return item text as string transformed by self.displayText()
     """
     # return qstr(item.text()) # convert to "normal" string
     return qstr(self.displayText(item.text(), QtCore.QLocale()))
Beispiel #32
0
 def text(self, item):
     """
     Return item text as string transformed by self.displayText()
     """
     # return qstr(item.text()) # convert to "normal" string
     return  qstr(self.displayText(item.text(), QtCore.QLocale()))
Beispiel #33
0
    def frmt2float(self, y, frmt=None):
        """
        Return floating point representation for fixpoint scalar `y` given in
        format `frmt`.

        When input format is float, return unchanged.

        Else:

        - Remove illegal characters and leading '0's
        - Count number of fractional places `frc_places` and remove radix point
        - Calculate decimal, fractional representation `y_dec` of string,
          using the base and the number of fractional places
        - Calculate two's complement for `W` bits (only for negative bin and hex numbers)
        - Calculate fixpoint float representation `y_float = fixp(y_dec, scaling='div')`,
          dividing the result by `scale`.

        Parameters
        ----------
        y: scalar or string
            to be quantized with the numeric base specified by `frmt`.

        frmt: string (optional)
            any of the formats `float`, `dec`, `bin`, `hex`, `csd`)
            When `frmt` is unspecified, the instance parameter `self.frmt` is used

        Returns
        -------
        quantized floating point (`dtype=np.float64`) representation of input string
        """
        if y == "":
            return 0

        if frmt is None:
            frmt = self.frmt
        frmt = frmt.lower()
        y_float = y_dec = None

        if frmt == 'float32':
            float_frmt = np.float32
        elif frmt == 'float16':
            float_frmt = np.float16

        if frmt == 'float':
            # this handles floats, np scalars + arrays and strings / string arrays
            try:
                y_float = np.float64(y)
            except ValueError:
                try:
                    y_float = np.complex(y).real
                except Exception as e:
                    y_float = None
                    logger.warning("Can't convert {0}: {1}".format(y, e))
            return y_float

        else:  # {'dec', 'bin', 'hex', 'csd'}
            # Find the number of places before the first radix point (if there is one)
            # and join integer and fractional parts
            # when returned string is empty, skip general conversions and rely on error handling
            # of individual routines
            # remove illegal characters and trailing zeros
            val_str = re.sub(self.FRMT_REGEX[frmt], r'', qstr(y)).lstrip('0')
            if len(val_str) > 0:
                val_str = val_str.replace(
                    ',', '.')  # ',' -> '.' for German-style numbers
                if val_str[
                        0] == '.':  # prepend '0' when the number starts with '.'
                    val_str = '0' + val_str

                # count number of fractional places in string
                try:
                    _, frc_str = val_str.split(
                        '.')  # split into integer and fractional places
                    frc_places = len(frc_str)
                except ValueError:  # no fractional part
                    frc_places = 0

                raw_str = val_str.replace(
                    '.', '')  # join integer and fractional part

                logger.debug("y={0}, val_str={1}, raw_str={2} ".format(
                    y, val_str, raw_str))
            else:
                return 0.0

        # (1) calculate the decimal value of the input string using np.float64()
        #     which takes the number of decimal places into account.
        # (2) quantize and saturate
        # (3) divide by scale
        if frmt == 'dec':
            # try to convert string -> float directly with decimal point position
            try:
                y_dec = y_float = self.fixp(val_str, scaling='div')
            except Exception as e:
                logger.warning(e)

        elif frmt in {'hex', 'bin'}:
            # - Glue integer and fractional part to a string without radix point
            # - Check for a negative sign, use this information only in the end
            # - Divide by <base> ** <number of fractional places> for correct scaling
            # - Strip MSBs outside fixpoint range
            # - Transform numbers in negative 2's complement to negative floats.
            # - Calculate the fixpoint representation for correct saturation / quantization
            neg_sign = False
            try:
                if raw_str[0] == '-':
                    neg_sign = True
                    raw_str = raw_str.lstrip('-')

                y_dec = abs(int(raw_str, self.base) / self.base**frc_places)

                if y_dec == 0:  # avoid log2(0)
                    return 0

                int_bits = max(int(np.floor(np.log2(y_dec))) + 1, 0)
                # When number is outside fixpoint range, discard MSBs:
                if int_bits > self.WI + 1:
                    if frmt == 'hex':
                        raw_str = np.binary_repr(int(raw_str, 16))
                    # discard the upper bits outside the valid range
                    raw_str = raw_str[int_bits - self.WI - 1:]

                    # recalculate y_dec for truncated string
                    y_dec = int(raw_str, 2) / self.base**frc_places

                    if y_dec == 0:  # avoid log2(0) error in code below
                        return 0

                    int_bits = max(int(np.floor(np.log2(y_dec))) + 1,
                                   0)  # ... and int_bits
                # now, y_dec is in the correct range:
                if int_bits <= self.WI:  # positive number
                    pass
                elif int_bits == self.WI + 1:  # negative, calculate 2's complemente
                    y_dec = y_dec - (1 << int_bits)
                # quantize / saturate / wrap & scale the integer value:
                if neg_sign:
                    y_dec = -y_dec
                y_float = self.fixp(y_dec, scaling='div')
            except Exception as e:
                logger.warning(e)
                y_dec = y_float = None

            logger.debug("MSB={0} | LSB={1} | scale={2}".format(
                self.MSB, self.LSB, self.scale))
            logger.debug("y_in={0} | y_dec={1}".format(y, y_dec))
        # ----
        elif frmt == 'csd':
            # - Glue integer and fractional part to a string without radix point
            # - Divide by 2 ** <number of fractional places> for correct scaling
            # - Calculate fixpoint representation for saturation / overflow effects

            y_dec = csd2dec_vec(raw_str)  # csd -> integer
            if y_dec is not None:
                y_float = self.fixp(y_dec / 2**frc_places, scaling='div')
        # ----
        else:
            logger.error('Unknown output format "%s"!'.format(frmt))

        if frmt != "float":
            logger.debug("MSB={0:g} |  scale={1:g} | raw_str={2} | val_str={3}"\
                         .format(self.MSB, self.scale, raw_str, val_str))
            logger.debug("y={0} | y_dec = {1} | y_float={2}".format(
                y, y_dec, y_float))

        if y_float is not None:
            return y_float
        else:
            return 0.0
Beispiel #34
0
    def _construct_UI(self, **kwargs):
        """ Construct widget from default settings, """

        # default settings
        dict_ui = {
            'label': 'WI.WF',
            'lbl_sep': '.',
            'max_led_width': 30,
            'WI': 0,
            'WI_len': 2,
            'tip_WI': 'Number of integer bits',
            'WF': 15,
            'WF_len': 2,
            'tip_WF': 'Number of fractional bits',
            'enabled': True,
            'visible': True,
            'fractional': True
        }  #: default values
        for k, v in kwargs.items():
            if k not in dict_ui:
                logger.warning("Unknown key {0}".format(k))
            else:
                dict_ui.update({k: v})
        # dict_ui.update(map(kwargs)) # same as above?

        if not dict_ui['fractional']:
            dict_ui['WF'] = 0
        self.WI = dict_ui['WI']
        self.WF = dict_ui['WF']

        lblW = QLabel(to_html(dict_ui['label'], frmt='bi'), self)
        self.ledWI = QLineEdit(self)
        self.ledWI.setToolTip(dict_ui['tip_WI'])
        self.ledWI.setMaxLength(dict_ui['WI_len'])  # maximum of 2 digits
        self.ledWI.setFixedWidth(
            dict_ui['max_led_width'])  # width of lineedit in points(?)

        lblDot = QLabel(dict_ui['lbl_sep'], self)
        lblDot.setVisible(dict_ui['fractional'])

        self.ledWF = QLineEdit(self)
        self.ledWF.setToolTip(dict_ui['tip_WF'])
        self.ledWF.setMaxLength(dict_ui['WI_len'])  # maximum of 2 digits
        self.ledWF.setFixedWidth(
            dict_ui['max_led_width'])  # width of lineedit in points(?)
        self.ledWF.setVisible(dict_ui['fractional'])

        layH = QHBoxLayout()
        layH.addWidget(lblW)
        layH.addStretch()
        layH.addWidget(self.ledWI)
        layH.addWidget(lblDot)
        layH.addWidget(self.ledWF)
        layH.setContentsMargins(0, 0, 0, 0)

        frmMain = QFrame(self)
        frmMain.setLayout(layH)

        layVMain = QVBoxLayout()  # Widget main layout
        layVMain.addWidget(frmMain)
        layVMain.setContentsMargins(0, 5, 0, 0)  #*params['wdg_margins'])

        self.setLayout(layVMain)

        #----------------------------------------------------------------------
        # INITIAL SETTINGS
        #----------------------------------------------------------------------
        self.ledWI.setText(qstr(dict_ui['WI']))
        self.ledWF.setText(qstr(dict_ui['WF']))

        frmMain.setEnabled(dict_ui['enabled'])
        frmMain.setVisible(dict_ui['visible'])

        #----------------------------------------------------------------------
        # LOCAL SIGNALS & SLOTs
        #----------------------------------------------------------------------
        self.ledWI.editingFinished.connect(self.ui2dict)
        self.ledWF.editingFinished.connect(self.ui2dict)
Beispiel #35
0
 def displayText(self, text, locale):
     return "{:.{n_digits}g}".format(safe_eval(qstr(text), return_type='cmplx'), 
             n_digits = params['FMT_pz'])
Beispiel #36
0
 def displayText(self, text, locale):
     return "{:.{n_digits}g}".format(safe_eval(qstr(text),
                                               return_type='cmplx'),
                                     n_digits=params['FMT_pz'])
    def _construct_UI(self, **kwargs):
        """ 
        Construct widget from quantization dict, individual settings and
        the default dict below """

        # default settings
        dict_ui = {
            'label': 'WI.WF',
            'lbl_sep': '.',
            'max_led_width': 30,
            'WI': 0,
            'WI_len': 2,
            'tip_WI': 'Number of integer bits',
            'WF': 15,
            'WF_len': 2,
            'tip_WF': 'Number of fractional bits',
            'enabled': True,
            'visible': True,
            'fractional': True,
            'combo_visible': False,
            'combo_items': ['auto', 'full', 'man'],
            'tip_combo': 'Calculate Acc. width.',
            'lock_visible': False,
            'tip_lock': 'Lock input/output quantization.'
        }  #: default values

        if self.q_dict:
            dict_ui.update(self.q_dict)

        for k, v in kwargs.items():
            if k not in dict_ui:
                logger.warning("Unknown key {0}".format(k))
            else:
                dict_ui.update({k: v})

        if not dict_ui['fractional']:
            dict_ui['WF'] = 0
        self.WI = dict_ui['WI']
        self.WF = dict_ui['WF']
        self.W = int(self.WI + self.WF + 1)
        if self.q_dict:
            self.q_dict.update({'WI': self.WI, 'WF': self.WF, 'W': self.W})
        else:
            self.q_dict = {'WI': self.WI, 'WF': self.WF, 'W': self.W}

        lblW = QLabel(to_html(dict_ui['label'], frmt='bi'), self)

        self.cmbW = QComboBox(self)
        self.cmbW.addItems(dict_ui['combo_items'])
        self.cmbW.setVisible(dict_ui['combo_visible'])
        self.cmbW.setToolTip(dict_ui['tip_combo'])
        self.cmbW.setObjectName("cmbW")

        self.butLock = QPushButton(self)
        self.butLock.setCheckable(True)
        self.butLock.setChecked(False)
        self.butLock.setVisible(dict_ui['lock_visible'])
        self.butLock.setToolTip(dict_ui['tip_lock'])

        self.ledWI = QLineEdit(self)
        self.ledWI.setToolTip(dict_ui['tip_WI'])
        self.ledWI.setMaxLength(dict_ui['WI_len'])  # maximum of 2 digits
        self.ledWI.setFixedWidth(
            dict_ui['max_led_width'])  # width of lineedit in points(?)
        self.ledWI.setObjectName("WI")

        lblDot = QLabel(dict_ui['lbl_sep'], self)
        lblDot.setVisible(dict_ui['fractional'])

        self.ledWF = QLineEdit(self)
        self.ledWF.setToolTip(dict_ui['tip_WF'])
        self.ledWF.setMaxLength(dict_ui['WI_len'])  # maximum of 2 digits
        self.ledWF.setFixedWidth(
            dict_ui['max_led_width'])  # width of lineedit in points(?)
        self.ledWF.setVisible(dict_ui['fractional'])
        self.ledWF.setObjectName("WF")

        layH = QHBoxLayout()
        layH.addWidget(lblW)
        layH.addStretch()
        layH.addWidget(self.cmbW)
        layH.addWidget(self.butLock)
        layH.addWidget(self.ledWI)
        layH.addWidget(lblDot)
        layH.addWidget(self.ledWF)
        layH.setContentsMargins(0, 0, 0, 0)

        frmMain = QFrame(self)
        frmMain.setLayout(layH)

        layVMain = QVBoxLayout()  # Widget main layout
        layVMain.addWidget(frmMain)
        layVMain.setContentsMargins(0, 5, 0, 0)  #*params['wdg_margins'])

        self.setLayout(layVMain)

        #----------------------------------------------------------------------
        # INITIAL SETTINGS
        #----------------------------------------------------------------------
        self.ledWI.setText(qstr(dict_ui['WI']))
        self.ledWF.setText(qstr(dict_ui['WF']))

        frmMain.setEnabled(dict_ui['enabled'])
        frmMain.setVisible(dict_ui['visible'])

        #----------------------------------------------------------------------
        # LOCAL SIGNALS & SLOTs
        #----------------------------------------------------------------------
        self.ledWI.editingFinished.connect(self.ui2dict)
        self.ledWF.editingFinished.connect(self.ui2dict)
        self.butLock.clicked.connect(self.but_clicked)
        self.cmbW.currentIndexChanged.connect(self.ui2dict)

        # initialize button icon
        self.but_clicked(self.butLock.isChecked())