I'm not sure if it is just me, but I just had a big struggle with the obspy.imaging.spectrogram script trying to add a colorbar to the figure. I would therefore like to suggest two permanent changes for the obspy.imaging.spectrogram script:
img = ax.imshow(specgram, interpolation="nearest", extent=extent, norm=norm, **kwargs)
instead of
ax.imshow(specgram, interpolation="nearest", extent=extent, **kwargs)
and
if axes:
return ax, img
instead of
if axes:
return ax
I'm under the impression that clipping is at the moment only applied in the log case. The first suggestion would change that for log and non-log frequency axes. To me it would also make sense to assign it permanently to img and return img along with ax so that a colobar can be easily created with sth like this:
ax, img = spectrogram(...)
fig.colorbar(img)
I am experiencing the same problem. May I ask how you solve it with the current version of obspy.imaging.spectrogram?
Thanks
How did you get a colorbar to work? I'm struggling with this right now too.
Hello EvaMuc and mat2py , I have been trying to get the above working but have had no luck. Any chance please you could provide details of the solution you ended up doing to get this to work. Many thanks in advance.
Hey wf215 - sorry, I never managed to get this to work! I've just left it and moved onto other things for the moment.
Hey mat2py, no worries. Thanks for replying.
Sorry for not answering earlier, this got lost in our flood of tickets, I guess..
It's pretty straightforward to access any lines, images, collections, you-name-it, directly from the Figure or Axes objects for further tweaking with matplotlib:
import matplotlib.pyplot as plt
from obspy import read
tr = read()[0]
fig = tr.spectrogram(show=False)
ax = fig.axes[0]
mappable = ax.images[0]
plt.colorbar(mappable=mappable, ax=ax)
fig = tr.spectrogram(show=False, log=True)
ax = fig.axes[0]
mappable = ax.collections[0]
plt.colorbar(mappable=mappable, ax=ax)
plt.show()
The type of matplotlib object to look up depends on whether it's a logarithmic plot (matplotlib.collections.QuadMesh object) or not (matplotlib.image.AxesImage object).
Many thanks megies for your answer. Really appreciated
Hey megie, thanks for the answer! First time I've got the colorbar() working so a big thanks for that.
Got a follow up question, if that's okay, as you seem good with this stuff. I want to do this but I already have the figure as subplots and so this code doesn't seem to quite work for that situation:
def plotwaveyspec(spl1,fmin=0.1,fmax=20):
from obspy.imaging.spectrogram import spectrogram
#info
beg = spl1[0].stats.starttime
end = spl1[0].stats.endtime
#setup figure
fig = plt.figure()
#example code
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)
ax = fig.axes[0]
mappable = ax.images[0]
plt.colorbar(mappable=mappable,ax=ax)
ax2.set_ylim(fmin, fmax)
plt.show()
#print some info
print('Figure starttime = %s'%beg)
print('Figure endtime = %s'%end)
note: spl1 is just a slice of a trace (quicker to plot and test than the whole trace)
The plt.colorbar() line only has one input and I thought that the ax= input referred to where you wanted to put the colorbar (in the same way as the spectrogram ax= input), but you seem to be using it as a data input?
I have an axis set up for the colorbar already (ax3) and so I would think I would need the plt.colorbar() line to be:
plt.colorbar(mappable=mappable, cax=ax3)
instead but that isn't working either. Both options come out with the figure below and shows the error after the figure

Traceback (most recent call last):
File "<ipython-input-30-aaa2b403062f>", line 1, in <module>
plotwaveyspec(spl1)
File "<ipython-input-29-0a93f39d1abf>", line 25, in plotwaveyspec
ax = fig.axes[0]
TypeError: 'Axes' object does not support indexing
Many thanks for your help if you can see the mistake/fix!
Cheers
I actually just managed to solve it. If anyone else has the problem, replace the spectrogram plot section with:
#plot spectrogram (bottom subfigure)
spl2 = spl1[0]
fig = spl2.spectrogram(show=False, axes=ax2)
#ax = fig.axes[1]
mappable = ax2.images[0]
plt.colorbar(mappable=mappable, cax=ax3)
ax2.set_ylim(fmin, fmax)
plt.show()

Thanks again for the help megies
You should consider using a different colormap.. :-) https://www.youtube.com/watch?v=xAoljeRJ3lU
Most helpful comment
Sorry for not answering earlier, this got lost in our flood of tickets, I guess..
It's pretty straightforward to access any lines, images, collections, you-name-it, directly from the Figure or Axes objects for further tweaking with matplotlib:
The type of matplotlib object to look up depends on whether it's a logarithmic plot (
matplotlib.collections.QuadMeshobject) or not (matplotlib.image.AxesImageobject).