Adding Colorbar to a Spectrogram

I'm trying to add a Colorbar to a spectrogram. I have tried every example and question thread I have found online and none have solved this issue

Note that 'spl1' (data splice 1) is a trace from ObsPy.

My code is:

fig = plt.figure()
ax1 = fig.add_axes([0.1, 0.75, 0.7, 0.2]) #[left bottom width height]
ax2 = fig.add_axes([0.1, 0.1, 0.7, 0.60], sharex=ax1)
ax3 = fig.add_axes([0.83, 0.1, 0.03, 0.6])

t = np.arange(spl1[0].stats.npts) / spl1[0].stats.sampling_rate
ax1.plot(t, spl1[0].data, 'k')

ax,spec = spectrogram(spl1[0].data,spl1[0].stats.sampling_rate, show=False, axes=ax2)
ax2.set_ylim(0.1, 15)
fig.colorbar(spec, cax=ax3)

It comes out with the error:

Traceback (most recent call last):

  File "<ipython-input-18-61226ccd2d85>", line 14, in <module>
    ax,spec = spectrogram(spl1[0].data,spl1[0].stats.sampling_rate, show=False, axes=ax2)

TypeError: 'Axes' object is not iterable

Best result so far:

Replacing the last 3 lines above with:

ax = spectrogram(spl1[0].data,spl1[0].stats.sampling_rate, show=False, axes=ax2)
ax2.set_ylim(0.1, 15)
fig.colorbar(ax,cax=ax3)

Produces this: 波形和谱图

and this error for the colorbar:

axes object has no attribute 'autoscale_None'

I don't seem to be able to find a way to get the colorbar on the right to work.

Solutions?

One of the solutions I have seen is that you need to create an 'image' of your data using imshow(), however I don't get an output for that from Spectrogram(), only 'ax'. I have seen places try with the 'ax,spec' output from spectrogram() but that is causing the TypeError.

  • Very similar code I found but didn't work https://www.nicotrebbin.de/wp-content/uploads/2012/03/bachelorthesis.pdf (ctrl+f 'colorbar')
  • Looked at code examples from a related question
  • imshow() suggestions and example - can't get an output from spectrogram to turn into an image. That second link, I also can't get the mlpy module to work (it doesn't think there's a mlpy.wavelet function)
  • This problem was addressed in an improvement post for obspy but the solution he stated he found was not given
  • I hope someone can give a hand with this - I've been working on this all day now!


    Solved it, with help from this link. It doesn't show decibels yet but the primary issue was getting the colorbar:

    from obspy.imaging.spectrogram import spectrogram
    fig = plt.figure()
    ax1 = fig.add_axes([0.1, 0.75, 0.7, 0.2]) #[left bottom width height]
    ax2 = fig.add_axes([0.1, 0.1, 0.7, 0.60], sharex=ax1)
    ax3 = fig.add_axes([0.83, 0.1, 0.03, 0.6])
    
    #make time vector
    t = np.arange(spl1[0].stats.npts) / spl1[0].stats.sampling_rate
    
    #plot waveform (top subfigure)    
    ax1.plot(t, spl1[0].data, 'k')
    
    #plot spectrogram (bottom subfigure)
    spl2 = spl1[0]
    fig = spl2.spectrogram(show=False, axes=ax2)
    mappable = ax2.images[0]
    plt.colorbar(mappable=mappable, cax=ax3)
    

    产生的数字


    I am assuming you are using matplotlib.pyplot. It has strightforward calls for color in the form of matplotlib.pyplot.plot(x-cordinates , y-co-ordinates, color)

    An example implementation is as below.

    """Plots
    Time in MS Vs Amplitude in DB of a input wav signal
    """
    
    import numpy
    import matplotlib.pyplot as plt
    import pylab
    from scipy.io import wavfile
    from scipy.fftpack import fft
    
    
    myAudio = "audio.wav"
    
    #Read file and get sampling freq [ usually 44100 Hz ]  and sound object
    samplingFreq, mySound = wavfile.read(myAudio)
    
    #Check if wave file is 16bit or 32 bit. 24bit is not supported
    mySoundDataType = mySound.dtype
    
    #We can convert our sound array to floating point values ranging from -1 to 1 as follows
    
    mySound = mySound / (2.**15)
    
    #Check sample points and sound channel for duel channel(5060, 2) or  (5060, ) for mono channel
    
    mySoundShape = mySound.shape
    samplePoints = float(mySound.shape[0])
    
    #Get duration of sound file
    signalDuration =  mySound.shape[0] / samplingFreq
    
    #If two channels, then select only one channel
    mySoundOneChannel = mySound[:,0]
    
    #Plotting the tone
    
    # We can represent sound by plotting the pressure values against time axis.
    #Create an array of sample point in one dimension
    timeArray = numpy.arange(0, samplePoints, 1)
    
    #
    timeArray = timeArray / samplingFreq
    
    #Scale to milliSeconds
    timeArray = timeArray * 1000
    
    #Plot the tone
    plt.plot(timeArray, mySoundOneChannel, color='G')
    plt.xlabel('Time (ms)')
    plt.ylabel('Amplitude')
    plt.show()
    
    
    #Plot frequency content
    #We can get frquency from amplitude and time using FFT , Fast Fourier Transform algorithm
    
    #Get length of mySound object array
    mySoundLength = len(mySound)
    
    #Take the Fourier transformation on given sample point 
    #fftArray = fft(mySound)
    fftArray = fft(mySoundOneChannel)
    
    numUniquePoints = numpy.ceil((mySoundLength + 1) / 2.0)
    fftArray = fftArray[0:numUniquePoints]
    
    #FFT contains both magnitude and phase and given in complex numbers in real + imaginary parts (a + ib) format.
    #By taking absolute value , we get only real part
    
    fftArray = abs(fftArray)
    
    #Scale the fft array by length of sample points so that magnitude does not depend on
    #the length of the signal or on its sampling frequency
    
    fftArray = fftArray / float(mySoundLength)
    
    #FFT has both positive and negative information. Square to get positive only
    fftArray = fftArray **2
    
    #Multiply by two (research why?)
    #Odd NFFT excludes Nyquist point
    if mySoundLength % 2 > 0: #we've got odd number of points in fft
        fftArray[1:len(fftArray)] = fftArray[1:len(fftArray)] * 2
    
    else: #We've got even number of points in fft
        fftArray[1:len(fftArray) -1] = fftArray[1:len(fftArray) -1] * 2  
    
    freqArray = numpy.arange(0, numUniquePoints, 1.0) * (samplingFreq / mySoundLength);
    
    #Plot the frequency
    plt.plot(freqArray/1000, 10 * numpy.log10 (fftArray), color='B')
    plt.xlabel('Frequency (Khz)')
    plt.ylabel('Power (dB)')
    plt.show()
    
    #Get List of element in frequency array
    #print freqArray.dtype.type
    freqArrayLength = len(freqArray)
    print "freqArrayLength =", freqArrayLength
    numpy.savetxt("freqData.txt", freqArray, fmt='%6.2f')
    
    #Print FFtarray information
    print "fftArray length =", len(fftArray)
    numpy.savetxt("fftData.txt", fftArray)
    

    在这里输入图像描述在这里输入图像描述

    链接地址: http://www.djcxy.com/p/32184.html

    上一篇: 有没有一种补充的方式来获得像鼠标事件?

    下一篇: 将彩条添加到频谱图