Plot audio waveform and spectrogram overlap - python

I am working with audio using librosa, and I need to plot the spectrogram and waveform in the same display.
My code:
plt.figure(figsize=(14, 9))
plt.figure(1)
plt.subplot(211)
plt.title('Spectrogram')
librosa.display.specshow(stft_db, x_axis='time', y_axis='log')
plt.subplot(212)
plt.title('Audioform')
librosa.display.waveplot(y, sr=sr)
Using this code I get this plot
But I need something like this

According to librosa, you're able to provide the display methods with an axes to draw the item on, specshow, waveplot. I'd recommend defining your matplotlib figure and subplots outright, and then giving librosa the axes to plot them on.
fig = plt.figure(figsize=(14, 9)) #This setups the figure
ax1 = fig.subplots() #Creates the Axes object to display one of the plots
ax2 = ax1.twinx() #Creates a second Axes object that shares the x-axis
librosa.display.specshow(stft_db, x_axis='time', y_axis='log', ax=ax1)
librosa.display.waveplot(y, sr=sr, ax=ax2)
plt.show()
There might be some more formatting to be done to get the desired look, I'd recommend taking a look at this example from matplotlib, for a similar shared axes plot.

Instead of using subplots use the same axes of a single plot to display both the graphs.
fig = plt.figure(figsize=(14, 9))
ax = librosa.display.specshow(stft_db, x_axis='time', y_axis='log')
librosa.display.waveplot(y, sr=sr, ax=ax)
plt.show()

Related

How do you overlay a seaborn contour plot over multiple matplotlib subplots

I have a contour plot, as shown on the right, the axes of which are returned by a function, and separately a series of six matplotlib subplots displayed as shown on the left.
Sample code (with formatting and unnecessary code removed):
def contour_plot(df):
df = DataFrame(contour_list, columns = ['N0','DI'])
f, ax = plt.subplots(figsize=(7, 7))
sns.kdeplot(data = df, ax=ax, x='N0', y='DI', levels=10)
return f, ax
fig, ax = contour_plot(df)
for i in range(6):
plt.subplot(3,2,i+1)
plt.scatter(x=X, y=Y c=C, s=0.1)
plt.colorbar()
fig = plt.gcf()
fig.set_size_inches(12, 16)
fig.tight_layout()
I want to be able to overlay the contour over each of the other plots, but I'm not sure how to do this? I would hopefully also like to keep the colorbar of the subplot images. Can this be done?

Removing overlapping x-axis labels in pyplot

I'm new to python and attempting to chart some time series data. I'm using pyplot to create 3 stacked line charts which have the same x-axis (dates), but a different scale for the y-axes. However, each y-axis, as well as the x-axis for the bottom chart, have overlapping labels. There are labels generated from 0 to 1, as well as axis labels from my data set. How do I turn 'off' the auto-generated 0 to 1 labels on the y-axes and the bottom x-axis?
fig, ax = plt.subplots(3,1,sharex='all', squeeze=False, figsize=(12,8))
ax = fig.add_subplot(3,1,1)
plt.plot(df1['date'], df1['value'])
ax2 = fig.add_subplot(3,1,2)
plt.plot(df2['date'], df2['value'])
ax3 = fig.add_subplot(3,1,3)
plt.plot(df3['date'], df3['value'])
plt.show()
You can see the issue in the below picture. Any help is greatly appreciated!
You have already created subplots with all the axes in the initial assignment
fig, ax = plt.subplots(3,1,sharex='all', squeeze=False, figsize=(12,8))
therefore the following assignements of
ax = fig.add_subplot(3,1,1)
ax2 = fig.add_subplot(3,1,2)
ax3 = fig.add_subplot(3,1,3)
are not only unnecessary, but they seem to overlap the already created subplots (if you change it to add_subplot(2,1,1) you will notice it just starts dividing figure again and overlaying axes on top of each other).
What you want to do, is access the axes created in plt.subplots() call:
fig, ax = plt.subplots(3,1,sharex='all', squeeze=False, figsize=(12,8))
ax[0].plot(df1['date'], df1['value'])
ax[1].plot(df2['date'], df2['value'])
ax[2].plot(df3['date'], df3['value'])
plt.show()
Simulated Output:
Data from seaborn tips dataset

Using imshow() to create higher quality hist2d

I am playing around with volumetric data and I am trying to project a "cosmic web" like image.
I pretty much create a file path and open the data with a module that opens hdf5 files. The x and y values are denoted by indexing from a the file gas_pos and the histogram is weighted by different properties, gas_density in this case:
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import LinearSegmentedColormap
from matplotlib.ticker import LogFormatter
cmap = LinearSegmentedColormap.from_list('mycmap', ['black', 'steelblue', 'mediumturquoise', 'darkslateblue'])
fig = plt.figure()
ax = fig.add_subplot(111)
H = ax.hist2d(gas_pos[:,0]/0.7, gas_pos[:,1]/0.7, bins=500, cmap=cmap, norm=matplotlib.colors.LogNorm(), weights=gas_density);
cb = fig.colorbar(H[3], ax=ax, shrink=0.8, pad=0.01, orientation="horizontal", label=r'$ \rho\ [M_{\odot}\ \mathrm{kpc}^{-3}]$')
ax.tick_params(axis=u'both', which=u'both',length=0)
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
plt.show()
giving me this:
which is nice, but I want to up the quality and remove the grainyness of it. When I try imshow interpolation:
cmap = LinearSegmentedColormap.from_list('mycmap', ['black', 'steelblue', 'mediumturquoise', 'darkslateblue'])
fig = plt.figure()
ax = fig.add_subplot(111)
H = ax.hist2d(gas_pos[:,0]/0.7, gas_pos[:,1]/0.7, bins=500, cmap=cmap, norm=matplotlib.colors.LogNorm(), weights=gas_density);
ax.tick_params(axis=u'both', which=u'both',length=0)
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)
im = ax.imshow(H[0], cmap=cmap, interpolation='sinc', norm=matplotlib.colors.LogNorm())
cb = fig.colorbar(H[3], ax=ax, shrink=0.8, pad=0.01, orientation="horizontal", label=r'$ \rho\ [M_{\odot}\ \mathrm{kpc}^{-3}]$')
plt.show()
Am I using this incorrectly? or is there something better I can use to modify the pixelation?
If anyone is wanting to play with my data, I will upload the data later on today!
Using interpolation='sinc' is indeed a good method to smoothen a plot. Others would e.g. be "gaussian", "bicubic" or "spline16".
The problem you observe is that the imshow plot is plotted on top of the hist2d plot and thus takes its axes limits. Those limits seem to be smaller than the number of points in the imshow plot and therefore you only see part of the total data.
The solution is either not to plot the hist2d plot at all or at least to plot it into another subplot or figure.
Pursuing the first idea, you would calculate your histogram without plotting it, using numpy.histogram2d
H, xedges, yedges = np.histogram2d(gas_pos[:,0]/0.7, gas_pos[:,1]/0.7,
bins=500, weights=gas_density)
im = ax.imshow(H.T, cmap=cmap, interpolation='sinc', norm=matplotlib.colors.LogNorm())
I would also recommend reading the numpy.histogram2d documentation, which includes an example of plotting the histogram output in matplotlib.
You'll probably want to set interpolation='None' in the call to imshow, instead of interpolation='sinc'

Creating sparklines using matplotlib in python

I am working on matplotlib and created some graphs like bar chart, bubble chart and others.
Can some one please explain with an example what is difference between line graph and sparkline graph and how to draw spark line graphs in python using matplotlib ?
for example with the following code
import matplotlib.pyplot as plt
import numpy as np
x=[1,2,3,4,5]
y=[5,7,2,6,2]
plt.plot(x, y)
plt.show()
the line graph generated is the following:
But I couldn't get what is the difference between a line chart and a spark lien chart for the same data. Please help me understand
A sparkline is the same as a line plot but without axes or coordinates. They can be used to show the "shape" of the data in a compact way.
You can cram several line plots in the same figure just by using subplots and changing properties of the resulting Axes for each subplot:
data = np.cumsum(np.random.rand(1000)-0.5)
data = data - np.mean(data)
fig = plt.figure()
ax1 = fig.add_subplot(411) # nrows, ncols, plot_number, top sparkline
ax1.plot(data, 'b-')
ax1.axhline(c='grey', alpha=0.5)
ax2 = fig.add_subplot(412, sharex=ax1)
ax2.plot(data, 'g-')
ax2.axhline(c='grey', alpha=0.5)
ax3 = fig.add_subplot(413, sharex=ax1)
ax3.plot(data, 'y-')
ax3.axhline(c='grey', alpha=0.5)
ax4 = fig.add_subplot(414, sharex=ax1) # bottom sparkline
ax4.plot(data, 'r-')
ax4.axhline(c='grey', alpha=0.5)
for axes in [ax1, ax2, ax3, ax4]: # remove all borders
plt.setp(axes.get_xticklabels(), visible=False)
plt.setp(axes.get_yticklabels(), visible=False)
plt.setp(axes.get_xticklines(), visible=False)
plt.setp(axes.get_yticklines(), visible=False)
plt.setp(axes.spines.values(), visible=False)
# bottom sparkline
plt.setp(ax4.get_xticklabels(), visible=True)
plt.setp(ax4.get_xticklines(), visible=True)
ax4.xaxis.tick_bottom() # but onlyt the lower x ticks not x ticks at the top
plt.tight_layout()
plt.show()
A sparkline graph is just a regular plot with all the axis removed. quite simple to do with matplotlib:
import matplotlib.pyplot as plt
import numpy as np
# create some random data
x = np.cumsum(np.random.rand(1000)-0.5)
# plot it
fig, ax = plt.subplots(1,1,figsize=(10,3))
plt.plot(x, color='k')
plt.plot(len(x)-1, x[-1], color='r', marker='o')
# remove all the axes
for k,v in ax.spines.items():
v.set_visible(False)
ax.set_xticks([])
ax.set_yticks([])
#show it
plt.show()

Matplotlib format the scale label

I have searched around SO and haven't been able to find how to format this text (I've also checked around google and the matplotlib docs)
I'm currently creating a figure and then adding 4 subplots in a 2x2 matrix format so I'm trying to scale down all the text:
fig = plt.figure()
ax1 = fig.add_subplot(221)
ax1.tick_params(labelsize='xx-small')
ax1.set_title(v, fontdict={'fontsize':'small'})
ax1.hist(results[v], histtype='bar', label='data', bins=bins, alpha=0.5)
ax1.hist(results[v+'_sim'], histtype='bar', label='truth', bins=bins, alpha=0.8)
ax1.legend(loc='best', fontsize='x-small')
You can set the parameters before plot:
plt.rcParams['xtick.labelsize'] = "xx-small"
plt.rcParams['ytick.labelsize'] = "xx-small"

Categories

Resources