Source code for pyfda.input_widgets.target_specs


# -*- coding: utf-8 -*-
#
# This file is part of the pyFDA project hosted at https://github.com/chipmuenk/pyfda
#
# Copyright © pyFDA Project Contributors
# Licensed under the terms of the MIT License
# (see file LICENSE in root directory for details)

"""
Widget collecting subwidgets for the target filter specifications (currently
only amplitude and frequency specs.)
"""
import sys

from pyfda.libs.compat import (
    QWidget, QLabel, QFont, QFrame, pyqtSignal, Qt, QHBoxLayout, QVBoxLayout)

import pyfda.filterbroker as fb
from pyfda.libs.pyfda_lib import pprint_log, first_item
from pyfda.input_widgets import amplitude_specs, freq_specs
from pyfda.pyfda_rc import params

import logging
logger = logging.getLogger(__name__)


[docs] class TargetSpecs(QWidget): """ Build and update widget for entering the target specifications (frequencies and amplitudes) like F_SB, F_PB, A_SB, etc. """ # class variables (shared between instances if more than one exists) sig_rx = pyqtSignal(object) # incoming sig_tx = pyqtSignal(object) # outgoing sig_tx_local = pyqtSignal(object) # outgoing to lower hierarchies from pyfda.libs.pyfda_qt_lib import emit def __init__(self, parent=None, title="Target Specs", objectName=""): super(TargetSpecs, self).__init__(parent) self.title = title self.setObjectName(objectName) self._construct_UI() # ============================================================================= #------------------------------------------------------------------------------
[docs] def process_sig_rx(self, dict_sig=None): """ Process signals coming in via subwidgets and sig_rx """ # logger.warning(f"SIG_RX: {first_item(dict_sig)}") if dict_sig['id'] == id(self): logger.warning("Stopped infinite loop.") return elif 'view_changed' in dict_sig and dict_sig['view_changed'] == 'f_S': # update target frequencies with new f_S self.emit(dict_sig, sig_name='sig_tx_local') elif 'data_changed' in dict_sig and dict_sig['data_changed'] == 'filter_loaded': self.emit(dict_sig, sig_name='sig_tx_local') else: return
# ============================================================================= def _construct_UI(self): """ Construct user interface """ # subwidget for Frequency Specs self.f_specs = freq_specs.FreqSpecs(self, title="Frequency", objectName="freq_specs_targ") # subwidget for Amplitude Specs self.a_specs = amplitude_specs.AmplitudeSpecs(self, title="Ripple", objectName="amplitude_specs_targ") self.a_specs.setVisible(True) """ LAYOUT """ bfont = QFont() bfont.setBold(True) lblTitle = QLabel(self) # field for widget title lblTitle.setText(self.title) lblTitle.setFont(bfont) # lblTitle.setContentsMargins(2,2,2,2) layHTitle = QHBoxLayout() layHTitle.addWidget(lblTitle) layHTitle.setAlignment(Qt.AlignHCenter) layHSpecs = QHBoxLayout() layHSpecs.setAlignment(Qt.AlignTop) layHSpecs.addWidget(self.f_specs) # frequency specs layHSpecs.addWidget(self.a_specs) # ampltitude specs layVSpecs = QVBoxLayout() layVSpecs.addLayout(layHTitle) layVSpecs.addLayout(layHSpecs) layVSpecs.setContentsMargins(0, 6, 0, 0) # (left, top, right, bottom) # This is the top level widget, encompassing the other widgets frmMain = QFrame(self) frmMain.setLayout(layVSpecs) self.layVMain = QVBoxLayout() # Widget main layout self.layVMain.addWidget(frmMain) self.layVMain.setContentsMargins(*params['wdg_margins']) self.setLayout(self.layVMain) # ---------------------------------------------------------------------- # GLOBAL SIGNALS & SLOTs # ---------------------------------------------------------------------- # process incoming global signals self.sig_rx.connect(self.process_sig_rx) # connect signals from f_specs and a_specs subwidget to higher hierarchies self.f_specs.sig_tx.connect(self.sig_tx) self.a_specs.sig_tx.connect(self.sig_tx) # pass on prefiltered received signals self.sig_tx_local.connect(self.f_specs.sig_rx) self.sig_tx_local.connect(self.a_specs.sig_rx) self.update_UI() # first time initialization # ------------------------------------------------------------------------------
[docs] def update_UI(self, new_labels=()): """ Called when a new filter design algorithm has been selected - Pass new frequency and amplitude labels to the amplitude and frequency spec widgets. The first element of the 'amp' and the 'freq' tuple is the state with 'u' for 'unused' and 'd' for disabled - The `filt_changed` signal is emitted already by `select_filter.py` """ if ('frq' in new_labels and len(new_labels['frq']) > 1 and new_labels['frq'][0] != 'i'): self.f_specs.show() self.f_specs.setEnabled(new_labels['frq'][0] != 'd') self.f_specs.update_UI(new_labels=new_labels['frq']) else: self.f_specs.hide() if ('amp' in new_labels and len(new_labels['amp']) > 1 and new_labels['amp'][0] != 'i'): self.a_specs.show() self.a_specs.setEnabled(new_labels['amp'][0] != 'd') self.a_specs.update_UI(new_labels=new_labels['amp']) else: self.a_specs.hide()
# ------------------------------------------------------------------------------ if __name__ == '__main__': """ Run widget standalone with `python -m pyfda.input_widgets.target_specs` """ from pyfda.libs.compat import QApplication from pyfda import pyfda_rc as rc app = QApplication(sys.argv) app.setStyleSheet(rc.qss_rc) # Read freq / amp / weight labels for current filter design rt = fb.fil[0]['rt'] ft = fb.fil[0]['ft'] fc = fb.fil[0]['fc'] if 'min' in fb.fil_tree[rt][ft][fc]: # extract target parameters from filter tree print(fb.fil_tree[rt][ft][fc]['min']['tspecs']) target_params = fb.fil_tree[rt][ft][fc]['min']['tspecs'][1] else: target_params = {} mainw = TargetSpecs(title="Test Specs") mainw.update_UI(target_params) app.setActiveWindow(mainw) mainw.show() sys.exit(app.exec_())