Максимальное значение графика python matplotlib specgram() отображается неверно

Я новичок в размещении вопросов здесь и пытаюсь следовать соответствующему этикету, поэтому, пожалуйста, помогите мне извлечь уроки из любых упущений или ошибок в моем вопросе.

Я использую спектрограмму для анализа акустических сигналов и запутался в двух аспектах результатов.

  1. Графики, кажется, имеют конец спектрограммы, помещенный во время последнего значения в массиве бинов, которое предполагается в середине последнего бина. Я ожидаю, что график закончится на значении end последнего бина.

  2. Значения bin-center, которые возвращаются в качестве оси времени, не совпадают со значениями из Matlab, но возможно, что в моих испытаниях есть другая настройка параметра.

Эти проблемы появляются в одном из примеров Matplotlib по адресу: http://matplotlib.org/1.4.0/examples/pylab_examples/specgram_demo.html

Значения бинов: 0,256, 0,768, 1,28…..19,2, 19,712.

Наиболее очевидная проблема заключается в том, что график спектрограммы заканчивается на 19,712, а не на ожидаемом значении 20,0.

Кто-нибудь может помочь прояснить? Является ли любая из этих проблем ошибкой? Или я что-то не так делаю?

Это связано с этим вопросом: comment46984395_29400923">Как заставить спектрограмму заполнить всю область фигуры с помощью matplotlib?

Заранее благодарим за любые рекомендации, которые вы можете предоставить.


person David J Perkel    schedule 02.04.2015    source источник


Ответы (2)


Да, сюжет заканчивается в середине последней корзины. Это, вероятно, не правильно.

Однако, несмотря ни на что, это не будет версия 2.0 по двум причинам.

Во-первых, конечная точка редко будет полностью соответствовать последней выборке, потому что она разделена на сегменты длиной NFFT с перекрытием noverlap, что вряд ли идеально впишется в длину сигнала, если вы не очень тщательно выберете длину сигнала. длина сегмента и перекрытие.

И даже тогда он никогда не достигнет 20.0, потому что numpy arange, как и в других диапазонах python, исключает последнее значение. Таким образом, t.max() равно 20.0-dt, что равно 19,9995. Опять же, это просто соглашение, отличное от того, что использует MATLAB.

Используя MATLAB 2014b и функцию спектрограммы, я запустил ее с теми же параметрами, что и в примере с matplotlib, обязательно приняв во внимание конечную точку диапазона. Я получаю те же моменты времени, что и с matplotlib.

person TheBlackCat    schedule 02.04.2015
comment
Хорошо, замечание принято относительно ожидаемых центров бинов. Я понимаю проблемы с длиной сегментов и т. д. У меня могут быть несоответствующие параметры между Matlab и matplotlib. Спасибо. Масштабирование сюжета по-прежнему остается проблемой. Я смотрю на обходные пути. В Matlab я брал данные, а затем перерисовывал себя с помощью imagesc(). Я изо всех сил пытался взять Pxx или значение im, возвращенное из specgram(), и построить их в новом окне. У меня возникли проблемы с пониманием аргументов степени и аспекта. Будем очень признательны за любые указания о том, как повторно отображать данные с правильным масштабированием по времени. - person David J Perkel; 02.04.2015
comment
Вы можете посмотреть исходный код метода specgram на сайте matplotlib github, чтобы узнать, как он это делает github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/ . Кроме того, вероятно, лучше задать новый вопрос здесь. - person TheBlackCat; 03.04.2015

Пожалуйста, взгляните на: Вырезание неиспользуемых частот в specgram matplotlib

Вот версия вышесказанного с различными аргументами, иллюстрирующая их эффекты:

from pylab import *
    from matplotlib import *
    # 100, 200, and 400 Hz sine 'wave'
    # Using more sample points
    dt = 0.00005
    t = arange(0.0, 20.000, 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
#x = s1 + s2 + nse # the signal
# Longer window
NFFT = 2048       # 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)
# Windowing+greater overlap + limiting bandwidth to plot:
# the minfreq and maxfreq args will limit the frequencies 
Pxx, freqs, bins, im = my_specgram(x, NFFT=NFFT, Fs=Fs, noverlap=2000, window=numpy.kaiser(NFFT,1.0), cmap=cm.gist_heat, minfreq = 0, maxfreq = 1000)
show()
close()

person Dan Stutts    schedule 02.04.2015