示例#1
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 {"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'])

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

        N = self.calc_n_points(abs(int(self.ledNPoints.text())))

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

        elif stim in {"Sine", "Rect"}:
            x = 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 = np.sign(x)
                title_str = r'Transient Response to Rect. Signal'
                H_str = r'$y_{rect}[n]$'

        elif stim == "Saw":
            x = 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 = np.random.randn(N)
            title_str = r'Transient Response to Gaussian Noise'
            H_str = r'$y_{gauss}[n]$'

        elif stim == "RandU":
            x = 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:  # has second order sections
            h = sig.sosfilt(sos, x)
            dc = sig.freqz(self.bb, self.aa, [0])
        else:  # no second order sections 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

        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:
            bottom = float(self.ledLogBottom.text())
            H_str = r'$|$ ' + H_str + '$|$ in dB'
            h = np.maximum(20 * np.log10(abs(h)), bottom)
            if self.cmplx:
                h_i = np.maximum(20 * np.log10(abs(h_i)), bottom)
                H_i_str = r'$\log$ ' + H_i_str + ' in dB'
        else:
            bottom = 0

        self._init_axes()

        #================ Main Plotting Routine =========================
        [ml, sl, bl] = self.ax_r.stem(t,
                                      h,
                                      bottom=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=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=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()
示例#2
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 {"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.setVisible(fb.fil[0]['freq_specs_unit'] == 'f_S')
        self.lblFreqUnit.setText(rt_label(fb.fil[0]['freq_specs_unit']))
        self.load_entry()
        
        
        self.bb = np.asarray(fb.fil[0]['ba'][0])
        self.aa = np.asarray(fb.fil[0]['ba'][1])
        sos = np.asarray(fb.fil[0]['sos'])

        self.f_S  = fb.fil[0]['f_S']
        
        N = self.calc_n_points(abs(int(self.ledNPoints.text())))

        t = np.linspace(0, N/self.f_S, N, endpoint=False)
        # calculate h[n]
        if stim == "Pulse":
            x = np.zeros(N)
            x[0] =1.0 # create dirac impulse as input signal
            title_str = r'Impulse Response'
            H_str = r'$h[n]$'
        elif stim == "Step":
            x = np.ones(N) # create step function
            title_str = r'Step Response'
            H_str = r'$h_{\epsilon}[n]$'
        elif stim == "StepErr":
            x = np.ones(N) # create step function
            title_str = r'Settling Error'
            H_str = r'$H(0) - h_{\epsilon}[n]$'
            
        elif stim in {"Sine", "Rect"}:
            x = np.sin(2 * np.pi * t * float(self.ledFreq.text()))
            if stim == "Sine":
                title_str = r'Response to Sine Signal'
                H_str = r'$h_{\sin}[n]$'
            else:
                x = np.sign(x)
                title_str = r'Response to Rect. Signal'
                H_str = r'$h_{rect}[n]$'
        else:
            x = sig.sawtooth(t * (float(self.ledFreq.text())* 2*np.pi))
            title_str = r'Response to Sawtooth Signal'
            H_str = r'$h_{saw}[n]$'

            
        if not np.any(sos): # no second order sections for current filter          
            h = sig.lfilter(self.bb, self.aa, x)
            dc = sig.freqz(self.bb, self.aa, [0])
        else:
#            print(sos)
            h = sig.sosfilt(sos, x)
            dc = sig.freqz(self.bb, self.aa, [0])
        
        if stim == "StepErr":
            h = h - abs(dc[1]) # subtract DC value from response


        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:
            bottom = float(self.ledLogBottom.text())
            H_str = r'$|$ ' + H_str + '$|$ in dB'
            h = np.maximum(20 * np.log10(abs(h)), bottom)
            if self.cmplx:
                h_i = np.maximum(20 * np.log10(abs(h_i)), bottom)
                H_i_str = r'$\log$ ' + H_i_str + ' in dB'
        else:
            bottom = 0

        self._init_axes()


        #================ Main Plotting Routine =========================
        [ml, sl, bl] = self.ax_r.stem(t, h, bottom=bottom, markerfmt='bo', linefmt='r')
        if self.chkPltStim.isChecked():
            [ms, ss, bs] = self.ax_r.stem(t, x, bottom=bottom, markerfmt='k*', linefmt='0.5')
            for stem in ss:
                stem.set_linewidth(0.5)
            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=bottom,
                                                markerfmt='rd', linefmt='b')
            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, color='b', alpha=.5)

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

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

        self.mplwidget.redraw()
示例#3
0
    def draw_impz_time(self):
        """
        (Re-)draw the time domain mplwidget
        """

        if self.y is None: # safety net for empty responses
            for ax in self.mplwidget_t.fig.get_axes(): # remove all axes
                self.mplwidget_t.fig.delaxes(ax)
            return

        mkfmt_i = 'd'
        
        self._init_axes_time()
        scale_i = scale_o = 1
        fx_min = -1.
        fx_max = 1.
        fx_title = ""
        if self.fx_sim: # fixpoint simulation enabled -> scale stimulus and response
            WI = WO = 1
            try:
                logger.info("hdl_dict = {0}".format(self.hdl_dict))
                WI = self.hdl_dict['QI']['W']
                WO = self.hdl_dict['QO']['W']

            except AttributeError as e:
                logger.error("Attribute error: {0}".format(e))

            except TypeError as e:
                logger.error("Type error: 'hdl_dict'={0},\n{1}".format(self.hdl_dict, e))

            except ValueError as e:
                logger.error("Value error: {0}".format(e))


            if self.ui.chk_fx_scale.isChecked():
                scale_i = 1 << WI-1
                fx_min = - (1 << WO-1)
                fx_max = (1 << WO-1) - 1
            else:
                scale_o = 1. / (1 << WO-1)
                fx_min = -1
                fx_max = 1 - scale_o

            logger.info("scale I:{0} O:{1}".format(scale_i, scale_o))

        if self.ui.chk_log_time.isChecked(): # log. scale for stimulus / response time domain
            H_str = '$|$' + self.H_str + '$|$ in dBV'
            x = np.maximum(20 * np.log10(abs(self.x * scale_i)), self.bottom_t)
            y = np.maximum(20 * np.log10(abs(self.y_r * scale_o)), self.bottom_t)
            win = np.maximum(20 * np.log10(abs(self.ui.win)), self.bottom_t)
            if self.cmplx:
                y_i = np.maximum(20 * np.log10(abs(self.y_i)), self.bottom_t)
                H_i_str = r'$|\Im\{$' + self.H_str + '$\}|$' + ' in dBV'
                H_str =   r'$|\Re\{$' + self.H_str + '$\}|$' + ' in dBV'
            fx_min = 20*np.log10(abs(fx_min))
            fx_max = fx_min
        else:
            x = self.x * scale_i
            y = self.y_r * scale_o
            win = self.ui.win
            if self.cmplx:
                y_i = self.y_i * scale_o
            
            if self.cmplx:           
                H_i_str = r'$\Im\{$' + self.H_str + '$\}$ in V'
                H_str = r'$\Re\{$' + self.H_str + '$\}$ in V'
            else:
                H_str = self.H_str + ' in V'

        if self.ui.chk_fx_range.isChecked() and self.fx_sim:
            self.ax_r.axhline(fx_max,0, 1, color='k', linestyle='--')
            self.ax_r.axhline(fx_min,0, 1, color='k', linestyle='--')
                        
        # --------------- Stimulus plot ----------------------------------
        plot_stim_dict = self.fmt_plot_stim.copy()
        plot_stim_fnc = self.plot_fnc(self.plt_time_stim, self.ax_r, plot_stim_dict, self.bottom_t)

        plot_stim_fnc(self.t[self.ui.N_start:], x[self.ui.N_start:], label='$x[n]$',
                 **plot_stim_dict)
        # Add plot markers, this is way faster than normal stem plotting
        if self.ui.chk_mrk_time_stim.isChecked() and self.plt_time_stim not in {"dots","none"}:
            self.ax_r.scatter(self.t[self.ui.N_start:], x[self.ui.N_start:], **self.fmt_mkr_stim)

        # --------------- Response plot ----------------------------------
        plot_resp_dict = self.fmt_plot_resp.copy()
        plot_resp_fnc = self.plot_fnc(self.plt_time_resp, self.ax_r, plot_resp_dict, self.bottom_t)
            
        plot_resp_fnc(self.t[self.ui.N_start:], y[self.ui.N_start:], label='$y[n]$',
                 **plot_resp_dict)
        # Add plot markers, this is way faster than normal stem plotting
        if self.ui.chk_mrk_time_resp.isChecked() and self.plt_time_resp not in {"dots","none"}:
            self.ax_r.scatter(self.t[self.ui.N_start:], y[self.ui.N_start:], **self.fmt_mkr_resp)

        # --------------- Window plot ----------------------------------
        if self.ui.chk_win_time.isChecked():
            self.ax_r.plot(self.t[self.ui.N_start:], win, c="gray", label=self.ui.window_type)

        self.ax_r.legend(loc='best', fontsize = 'small', fancybox=True, framealpha=0.5)

        # --------------- Complex response ----------------------------------
        if self.cmplx and self.plt_time_resp != "none":
            #plot_resp_dict = self.fmt_plot_resp.copy()
            plot_resp_fnc = self.plot_fnc(self.plt_time_resp, self.ax_i, plot_resp_dict, self.bottom_t)
                
            plot_resp_fnc(self.t[self.ui.N_start:], y_i[self.ui.N_start:], label='$y_i[n]$',
                     **plot_resp_dict)
            # Add plot markers, this is way faster than normal stem plotting
            if self.ui.chk_mrk_time_resp.isChecked() and self.plt_time_resp not in {"dots","none"}:
                self.ax_i.scatter(self.t[self.ui.N_start:], y_i[self.ui.N_start:], 
                                  marker=mkfmt_i, **self.fmt_mkr_resp)

#            [ml_i, sl_i, bl_i] = self.ax_i.stem(self.t[self.ui.N_start:], y_i[self.ui.N_start:],
#                bottom=self.bottom_t, markerfmt=mkfmt_i, label = '$y_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_xlabel(fb.fil[0]['plt_tLabel'])
            self.ax_i.set_ylabel(H_i_str + r'$\rightarrow $')
            self.ax_i.legend(loc='best', fontsize = 'small', fancybox=True, framealpha=0.5)            
        else:
            self.ax_r.set_xlabel(fb.fil[0]['plt_tLabel'])
            self.ax_r.set_ylabel(H_str + r'$\rightarrow $')
        
        self.ax_r.set_title(fx_title + self.title_str)
        self.ax_r.set_xlim([self.t[self.ui.N_start],self.t[self.ui.N_end-1]])
        expand_lim(self.ax_r, 0.02)
        

        if self.ACTIVE_3D: # not implemented / tested yet
            # plotting the stems
            for i in range(self.ui.N_start, self.ui.N_end):
              self.ax3d.plot([self.t[i], self.t[i]], [y[i], y[i]], [0, y_i[i]],
                             '-', linewidth=2, alpha=.5)

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

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

        self.redraw() # redraw currently active mplwidget
示例#4
0
    def draw_impz_time(self):
        """
        (Re-)draw the time domain mplwidget
        """

        if self.y is None:  # safety net for empty responses
            for ax in self.mplwidget_t.fig.get_axes():  # remove all axes
                self.mplwidget_t.fig.delaxes(ax)
            return

        mkfmt_i = 'd'

        self._init_axes_time()
        scale_i = scale_o = 1
        fx_min = -1.
        fx_max = 1.
        fx_title = ""
        if self.fx_sim:  # fixpoint simulation enabled -> scale stimulus and response
            WI = WO = 1
            try:
                logger.info("hdl_dict = {0}".format(self.hdl_dict))
                WI = self.hdl_dict['QI']['W']
                WO = self.hdl_dict['QO']['W']

            except AttributeError as e:
                logger.error("Attribute error: {0}".format(e))

            except TypeError as e:
                logger.error("Type error: 'hdl_dict'={0},\n{1}".format(
                    self.hdl_dict, e))

            except ValueError as e:
                logger.error("Value error: {0}".format(e))

            if self.ui.chk_fx_scale.isChecked():
                scale_i = 1 << WI - 1
                fx_min = -(1 << WO - 1)
                fx_max = (1 << WO - 1) - 1
            else:
                scale_o = 1. / (1 << WO - 1)
                fx_min = -1
                fx_max = 1 - scale_o

            logger.info("scale I:{0} O:{1}".format(scale_i, scale_o))

        if self.ui.chk_log_time.isChecked(
        ):  # log. scale for stimulus / response time domain
            H_str = '$|$' + self.H_str + '$|$ in dBV'
            x = np.maximum(20 * np.log10(abs(self.x * scale_i)), self.bottom_t)
            y = np.maximum(20 * np.log10(abs(self.y_r * scale_o)),
                           self.bottom_t)
            win = np.maximum(20 * np.log10(abs(self.ui.win)), self.bottom_t)
            if self.cmplx:
                y_i = np.maximum(20 * np.log10(abs(self.y_i)), self.bottom_t)
                H_i_str = r'$|\Im\{$' + self.H_str + '$\}|$' + ' in dBV'
                H_str = r'$|\Re\{$' + self.H_str + '$\}|$' + ' in dBV'
            fx_min = 20 * np.log10(abs(fx_min))
            fx_max = fx_min
        else:
            x = self.x * scale_i
            y = self.y_r * scale_o
            win = self.ui.win
            if self.cmplx:
                y_i = self.y_i * scale_o

            if self.cmplx:
                H_i_str = r'$\Im\{$' + self.H_str + '$\}$ in V'
                H_str = r'$\Re\{$' + self.H_str + '$\}$ in V'
            else:
                H_str = self.H_str + ' in V'

        if self.ui.chk_fx_range.isChecked() and self.fx_sim:
            self.ax_r.axhline(fx_max, 0, 1, color='k', linestyle='--')
            self.ax_r.axhline(fx_min, 0, 1, color='k', linestyle='--')

        # --------------- Stimulus plot ----------------------------------
        plot_stim_dict = self.fmt_plot_stim.copy()
        plot_stim_fnc = self.plot_fnc(self.plt_time_stim, self.ax_r,
                                      plot_stim_dict, self.bottom_t)

        plot_stim_fnc(self.t[self.ui.N_start:],
                      x[self.ui.N_start:],
                      label='$x[n]$',
                      **plot_stim_dict)
        # Add plot markers, this is way faster than normal stem plotting
        if self.ui.chk_mrk_time_stim.isChecked(
        ) and self.plt_time_stim not in {"dots", "none"}:
            self.ax_r.scatter(self.t[self.ui.N_start:], x[self.ui.N_start:],
                              **self.fmt_mkr_stim)

        # --------------- Response plot ----------------------------------
        plot_resp_dict = self.fmt_plot_resp.copy()
        plot_resp_fnc = self.plot_fnc(self.plt_time_resp, self.ax_r,
                                      plot_resp_dict, self.bottom_t)

        plot_resp_fnc(self.t[self.ui.N_start:],
                      y[self.ui.N_start:],
                      label='$y[n]$',
                      **plot_resp_dict)
        # Add plot markers, this is way faster than normal stem plotting
        if self.ui.chk_mrk_time_resp.isChecked(
        ) and self.plt_time_resp not in {"dots", "none"}:
            self.ax_r.scatter(self.t[self.ui.N_start:], y[self.ui.N_start:],
                              **self.fmt_mkr_resp)

        # --------------- Window plot ----------------------------------
        if self.ui.chk_win_time.isChecked():
            self.ax_r.plot(self.t[self.ui.N_start:],
                           win,
                           c="gray",
                           label=self.ui.window_type)

        self.ax_r.legend(loc='best',
                         fontsize='small',
                         fancybox=True,
                         framealpha=0.5)

        # --------------- Complex response ----------------------------------
        if self.cmplx and self.plt_time_resp != "none":
            #plot_resp_dict = self.fmt_plot_resp.copy()
            plot_resp_fnc = self.plot_fnc(self.plt_time_resp, self.ax_i,
                                          plot_resp_dict, self.bottom_t)

            plot_resp_fnc(self.t[self.ui.N_start:],
                          y_i[self.ui.N_start:],
                          label='$y_i[n]$',
                          **plot_resp_dict)
            # Add plot markers, this is way faster than normal stem plotting
            if self.ui.chk_mrk_time_resp.isChecked(
            ) and self.plt_time_resp not in {"dots", "none"}:
                self.ax_i.scatter(self.t[self.ui.N_start:],
                                  y_i[self.ui.N_start:],
                                  marker=mkfmt_i,
                                  **self.fmt_mkr_resp)

#            [ml_i, sl_i, bl_i] = self.ax_i.stem(self.t[self.ui.N_start:], y_i[self.ui.N_start:],
#                bottom=self.bottom_t, markerfmt=mkfmt_i, label = '$y_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_xlabel(fb.fil[0]['plt_tLabel'])
            self.ax_i.set_ylabel(H_i_str + r'$\rightarrow $')
            self.ax_i.legend(loc='best',
                             fontsize='small',
                             fancybox=True,
                             framealpha=0.5)
        else:
            self.ax_r.set_xlabel(fb.fil[0]['plt_tLabel'])
            self.ax_r.set_ylabel(H_str + r'$\rightarrow $')

        self.ax_r.set_title(fx_title + self.title_str)
        self.ax_r.set_xlim(
            [self.t[self.ui.N_start], self.t[self.ui.N_end - 1]])
        expand_lim(self.ax_r, 0.02)

        if self.ACTIVE_3D:  # not implemented / tested yet
            # plotting the stems
            for i in range(self.ui.N_start, self.ui.N_end):
                self.ax3d.plot([self.t[i], self.t[i]], [y[i], y[i]],
                               [0, y_i[i]],
                               '-',
                               linewidth=2,
                               alpha=.5)

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

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

        self.redraw()  # redraw currently active mplwidget
示例#5
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()
示例#6
0
    def draw_impz(self):
        """
        (Re-)draw the figure
        """
        f_unit = fb.fil[0]['freq_specs_unit']
        if f_unit in {"f_S", "f_Ny"}:
            unit_frmt = "i" # italic
        else:
            unit_frmt = None
        self.ui.lblFreqUnit1.setText(to_html(f_unit, frmt=unit_frmt))
        self.ui.lblFreqUnit2.setText(to_html(f_unit, frmt=unit_frmt))
        N_start = self.ui.N_start
        self.load_fs()
        self.init_axes()
        
        #================ Main Plotting Routine =========================
        if self.ui.chkMarker.isChecked():
            mkfmt_r = 'o'
            mkfmt_i = 'd'
        else:
            mkfmt_r = mkfmt_i = ' '
        if self.cmplx:           
            H_i_str = r'$\Im\{$' + self.H_str + '$\}$ in V'
            H_str = r'$\Re\{$' + self.H_str + '$\}$ in V'
        else:
            H_str = self.H_str + 'in V'

        if self.ui.chkLog.isChecked():
            H_str = r'$|$ ' + H_str + '$|$ in dBV'
            y = np.maximum(20 * np.log10(abs(self.y)), self.ui.bottom)
            if self.cmplx:
                y_i = np.maximum(20 * np.log10(abs(self.y_i)), self.ui.bottom)
                H_i_str = r'$\log$ ' + H_i_str + ' in dBV'
        else:
            self.ui.bottom = 0
            y = self.y
            y_i = self.y_i

        if self.ui.plt_time in {"Response", "Both"}:
            [ml, sl, bl] = self.ax_r.stem(self.t[N_start:], y[N_start:], 
                bottom=self.ui.bottom, markerfmt=mkfmt_r, label = '$y[n]$')

        if self.ui.plt_time in {"Stimulus", "Both"}:
            stem_fmt = params['mpl_stimuli']
            [ms, ss, bs] = self.ax_r.stem(self.t[N_start:], self.x[N_start:], 
                bottom=self.ui.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

        if self.cmplx and self.ui.plt_time in {"Response", "Both"}:
            [ml_i, sl_i, bl_i] = self.ax_i.stem(self.t[N_start:], y_i[N_start:],
                bottom=self.ui.bottom, markerfmt=mkfmt_i, label = '$y_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 $')
        
        self.ax_r.set_title(self.title_str)
        self.ax_r.set_xlim([self.t[N_start],self.t[self.ui.N_end-1]])
        expand_lim(self.ax_r, 0.02)

        # plot frequency domain =========================================
        if self.ui.plt_freq != "None":
            plt_response = self.ui.plt_freq in {"Response","Both"}
            plt_stimulus = self.ui.plt_freq in {"Stimulus","Both"}
            if plt_response and not plt_stimulus:
                XY_str = r'$|Y(\mathrm{e}^{\mathrm{j} \Omega})|$'
            elif not plt_response and plt_stimulus:
                XY_str = r'$|X(\mathrm{e}^{\mathrm{j} \Omega})|$'
            else:
                XY_str = r'$|X,Y(\mathrm{e}^{\mathrm{j} \Omega})|$'
            F = np.fft.fftfreq(self.ui.N, d = 1. / fb.fil[0]['f_S'])

            if plt_stimulus:
                X = self.X.copy()/np.sqrt(2) # enforce deep copy and convert to RMS
                self.Px = np.sum(np.square(self.X))
                if fb.fil[0]['freqSpecsRangeType'] == 'half':
                    X[1:] = 2 * X[1:] # correct for single-sided spectrum (except DC)
            if plt_response:
                Y = self.Y.copy()/np.sqrt(2) # enforce deep copy and convert to RMS
                self.Py = np.sum(np.square(self.Y))
                if fb.fil[0]['freqSpecsRangeType'] == 'half':
                    Y[1:] = 2 * Y[1:] # correct for single-sided spectrum (except DC)

            if self.ui.chkLogF.isChecked():
                unit = unit_P = "dBW"
                unit_nenbw = "dB"
                nenbw = 10 * np.log10(self.ui.nenbw)
                if plt_stimulus:
                    X = np.maximum(20 * np.log10(X), self.ui.bottom_f)
                    self.Px = 10*np.log10(self.Px)
                if plt_response:
                    Y = np.maximum(20 * np.log10(Y), self.ui.bottom_f)
                    self.Py = 10*np.log10(self.Py)
            else:
                unit = "Vrms"
                unit_P = "W"
                unit_nenbw = "bins"
                nenbw = self.ui.nenbw

            XY_str = XY_str + ' in ' + unit

            if fb.fil[0]['freqSpecsRangeType'] == 'sym':
            # shift X, Y and F by f_S/2
                if plt_response:
                    Y = np.fft.fftshift(Y)
                if plt_stimulus:
                    X = np.fft.fftshift(X)
                F = np.fft.fftshift(F)
            elif fb.fil[0]['freqSpecsRangeType'] == 'half':
                # only use the first half of X, Y and F
                if plt_response:
                    Y = Y[0:self.ui.N//2]
                if plt_stimulus:
                    X = X[0:self.ui.N//2]
                F = F[0:self.ui.N//2]
            else: # fb.fil[0]['freqSpecsRangeType'] == 'whole'
                # plot for F = 0 ... 1
                F = np.fft.fftshift(F) + fb.fil[0]['f_S']/2.

            handles = []
            labels = []
            if plt_stimulus:
                h, = self.ax_fft.plot(F, X, color =(0.5,0.5,0.5,0.5), lw=2)
                handles.append(h)
                labels.append("$P_X$ = {0:.3g} {1}".format(self.Px, unit_P))
            if plt_response:
                h, = self.ax_fft.plot(F, Y)
                handles.append(h)
                labels.append("$P_Y$ = {0:.3g} {1}".format(self.Py, unit_P))
                
            labels.append("$NENBW$ = {0:.4g} {1}".format(nenbw, unit_nenbw))
            labels.append("$CGAIN$  = {0:.4g}".format(self.ui.scale))
            handles.append(mpl_patches.Rectangle((0, 0), 1, 1, fc="white",ec="white", lw=0))
            handles.append(mpl_patches.Rectangle((0, 0), 1, 1, fc="white",ec="white", lw=0))
            self.ax_fft.legend(handles, labels, loc='best', fontsize = 'small',
                               fancybox=True, framealpha=0.5)
            

            self.ax_fft.set_xlabel(fb.fil[0]['plt_fLabel'])
            self.ax_fft.set_ylabel(XY_str)
            self.ax_fft.set_xlim(fb.fil[0]['freqSpecsRange'])
            if self.ui.plt_time == "None":
                self.ax_fft.set_title(self.title_str) # no time window, print title here
                
            if self.ui.chkLogF.isChecked():
                # create second axis scaled for noise power scale
                self.ax_fft_noise = self.ax_fft.twinx()
                self.ax_fft_noise.is_twin = True

                corr = 10*np.log10(self.ui.N / self.ui.nenbw) 
                mn, mx = self.ax_fft.get_ylim()
                self.ax_fft_noise.set_ylim(mn+corr, mx+corr)
                self.ax_fft_noise.set_ylabel(r'$P_N$ in dBW')

        if self.ACTIVE_3D: # not implemented / tested yet
            # plotting the stems
            for i in range(N_start, self.ui.N_end):
              self.ax3d.plot([self.t[i], self.t[i]], [y[i], y[i]], [0, y_i[i]],
                             '-', linewidth=2, alpha=.5)

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

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

        self.redraw()