Adding Colorbar to Spectrogram

I am trying to add a Colorbar to a spectrogram. I tried every example and question that I found on the Internet and no one solved this problem.

Note that "spl1" (data splicing 1) is a trace of 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) 

An error is issued:

 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:

Replacing the last 3 lines above:

 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 the following: Waveform and spectrogram plot

and this error is for colorbar:

 axes object has no attribute 'autoscale_None' 

I can't seem to find a way to get the color bar to the right of the job.

Solutions?

One of the solutions I saw is that you need to create an “image” of your data using imshow (), but I do not get the output for this from Spectrogram (), only “ax”. I have seen places try using the output of "ax, spec" from spectrogram (), but this raises a TypeError.

I hope someone can give a hand with this - I work on it all day!

+7
python spectrogram
source share
2 answers

Decided using this link . It doesn't show decibels yet, but the main problem 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) 

produced figure

+3
source share

I assume that you are using matplotlib.pyplot . It has direct color calls in the form of matplotlib.pyplot.plot(x-cordinates , y-co-ordinates, color)

An example implementation is presented 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) 

enter image description here enter image description here

0
source share

All Articles