Cutting of unused frequencies in specgram matplotlib

后端 未结 4 2103
醉话见心
醉话见心 2021-02-06 05:04

I have a signal with sampling rate 16e3, its frequency range is from 125 to 1000 Hz. So if i plot a specgram i get a pretty small colorrange because of all the unused frequencys

相关标签:
4条回答
  • 2021-02-06 05:36

    Here is an adapted version of this: http://matplotlib.org/examples/pylab_examples/specgram_demo.html which changes the range of frequencies that are plotted.

    #!/usr/bin/env python
    #### from the example
    #### 
    from pylab import *
    
    dt = 0.0005
    t = arange(0.0, 20.0, dt)
    s1 = sin(2*pi*100*t)
    s2 = 2*sin(2*pi*400*t)
    mask = where(logical_and(t>10, t<12), 1.0, 0.0)
    s2 = s2 * mask
    nse = 0.01*randn(len(t))
    x = s1 + s2 + nse # the signal
    
    NFFT = 1024       # the length of the windowing segments
    Fs = int(1.0/dt)  # the sampling frequency
    
    ax1 = subplot(211)
    plot(t, x)
    subplot(212, sharex=ax1)
    Pxx, freqs, bins, im = specgram(x, NFFT=NFFT, Fs=Fs, noverlap=900,
                                    cmap=cm.gist_heat)
    
    #### edited from the example
    #### 
    # here we get access to the axes
    x1,x2,y1,y2 = axis()
    # leave x range the same, change y (frequency) range
    axis((x1,x2,25,500))
    
    show()
    
    0 讨论(0)
  • 2021-02-06 05:42

    These days, there's an easier way to do this than when the question was asked: you can use matplotlib.pyplot.axis to set ymin and ymax to your desired frequencies. It's quite easy; here's a snippet from my program:

    plt.specgram(xmit, NFFT=65536, Fs=Fs)
    plt.axis(ymin=Fc-Fa*10, ymax=Fc+Fa*10)
    plt.show()
    
    0 讨论(0)
  • 2021-02-06 05:47

    specgram() is doing all the work for you. If you look in axes.py at the specgram function you can see how it works. The original function is in Python27\Lib\site-packages\matplotlib\axes.py on my computer.

        <snip>  
        Pxx, freqs, bins = mlab.specgram(x, NFFT, Fs, detrend,
             window, noverlap, pad_to, sides, scale_by_freq)
    
        Z = 10. * np.log10(Pxx)
        Z = np.flipud(Z)
    
        if xextent is None: xextent = 0, np.amax(bins)
        xmin, xmax = xextent
        freqs += Fc
        extent = xmin, xmax, freqs[0], freqs[-1]
        im = self.imshow(Z, cmap, extent=extent, **kwargs)
        self.axis('auto')
    
        return Pxx, freqs, bins, im
    

    You might have to make your own function modeled on this and clip the Pxx data to suit your needs.

        Pxx, freqs, bins = mlab.specgram(x, NFFT, Fs, detrend,
             window, noverlap, pad_to, sides, scale_by_freq)
        # ****************
        # create a new limited Pxx and freqs
        # 
        # ****************
        Z = 10. * np.log10(Pxx)
        Z = np.flipud(Z)
    

    Pxx is a 2d array with a shape of (len(freqs),len(bins)

    >>> Pxx.shape
    (129, 311)
    >>> freqs.shape
    (129,)
    >>> bins.shape
    (311,)
    >>> 
    

    This will limit Pxx and freqs

    Pxx = Pxx[(freqs >= 125) & (freqs <= 1000)]
    freqs = freqs[(freqs >= 125) & (freqs <= 1000)]
    

    Here is a complete solution - my_specgram() - used with the specgram_demo from the gallery.

    from pylab import *
    from matplotlib import *
    
    
    # 100, 400 and 200 Hz sine 'wave'
    dt = 0.0005
    t = arange(0.0, 20.0, dt)
    s1 = sin(2*pi*100*t)
    s2 = 2*sin(2*pi*400*t)
    s3 = 2*sin(2*pi*200*t)
    
    # create a transient "chirp"
    mask = where(logical_and(t>10, t<12), 1.0, 0.0)
    s2 = s2 * mask
    
    # add some noise into the mix
    nse = 0.01*randn(len(t))
    
    x = s1 + s2 + +s3 + nse # the signal
    NFFT = 1024       # the length of the windowing segments
    Fs = int(1.0/dt)  # the sampling frequency
    
    # modified specgram()
    def my_specgram(x, NFFT=256, Fs=2, Fc=0, detrend=mlab.detrend_none,
                 window=mlab.window_hanning, noverlap=128,
                 cmap=None, xextent=None, pad_to=None, sides='default',
                 scale_by_freq=None, minfreq = None, maxfreq = None, **kwargs):
        """
        call signature::
    
          specgram(x, NFFT=256, Fs=2, Fc=0, detrend=mlab.detrend_none,
                   window=mlab.window_hanning, noverlap=128,
                   cmap=None, xextent=None, pad_to=None, sides='default',
                   scale_by_freq=None, minfreq = None, maxfreq = None, **kwargs)
    
        Compute a spectrogram of data in *x*.  Data are split into
        *NFFT* length segments and the PSD of each section is
        computed.  The windowing function *window* is applied to each
        segment, and the amount of overlap of each segment is
        specified with *noverlap*.
    
        %(PSD)s
    
          *Fc*: integer
            The center frequency of *x* (defaults to 0), which offsets
            the y extents of the plot to reflect the frequency range used
            when a signal is acquired and then filtered and downsampled to
            baseband.
    
          *cmap*:
            A :class:`matplotlib.cm.Colormap` instance; if *None* use
            default determined by rc
    
          *xextent*:
            The image extent along the x-axis. xextent = (xmin,xmax)
            The default is (0,max(bins)), where bins is the return
            value from :func:`mlab.specgram`
    
          *minfreq, maxfreq*
            Limits y-axis. Both required
    
          *kwargs*:
    
            Additional kwargs are passed on to imshow which makes the
            specgram image
    
          Return value is (*Pxx*, *freqs*, *bins*, *im*):
    
          - *bins* are the time points the spectrogram is calculated over
          - *freqs* is an array of frequencies
          - *Pxx* is a len(times) x len(freqs) array of power
          - *im* is a :class:`matplotlib.image.AxesImage` instance
    
        Note: If *x* is real (i.e. non-complex), only the positive
        spectrum is shown.  If *x* is complex, both positive and
        negative parts of the spectrum are shown.  This can be
        overridden using the *sides* keyword argument.
    
        **Example:**
    
        .. plot:: mpl_examples/pylab_examples/specgram_demo.py
    
        """
    
        #####################################
        # modified  axes.specgram() to limit
        # the frequencies plotted
        #####################################
    
        # this will fail if there isn't a current axis in the global scope
        ax = gca()
        Pxx, freqs, bins = mlab.specgram(x, NFFT, Fs, detrend,
             window, noverlap, pad_to, sides, scale_by_freq)
    
        # modified here
        #####################################
        if minfreq is not None and maxfreq is not None:
            Pxx = Pxx[(freqs >= minfreq) & (freqs <= maxfreq)]
            freqs = freqs[(freqs >= minfreq) & (freqs <= maxfreq)]
        #####################################
    
        Z = 10. * np.log10(Pxx)
        Z = np.flipud(Z)
    
        if xextent is None: xextent = 0, np.amax(bins)
        xmin, xmax = xextent
        freqs += Fc
        extent = xmin, xmax, freqs[0], freqs[-1]
        im = ax.imshow(Z, cmap, extent=extent, **kwargs)
        ax.axis('auto')
    
        return Pxx, freqs, bins, im
    
    # plot
    ax1 = subplot(211)
    plot(t, x)
    subplot(212, sharex=ax1)
    
    # the minfreq and maxfreq args will limit the frequencies 
    Pxx, freqs, bins, im = my_specgram(x, NFFT=NFFT, Fs=Fs, noverlap=900, 
                                    cmap=cm.Accent, minfreq = 180, maxfreq = 220)
    show()
    close()
    
    0 讨论(0)
  • 2021-02-06 05:50

    specgram() returns (Pxx, freqs, bins, im), where im is AxesImage instance [1]. You could use it to set the limits of your plot:

    Pxx, freqs, bins, im = plt.specgram(signal, Fs=fs)
    im.set_ylim((125,1000))
    

    [1] http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.specgram

    0 讨论(0)
提交回复
热议问题