How to plot the sound wave, mfcc,and mel spectrogram on a single figure? - matplotlib

I have a folder containing multiple wav files (currently say 4). I want to plot the wav, its mfcc and mel spectrogram in a row , so finally a figure with 12 plots(each row with three figure, and hence four rows). I am not able to plot the graph, only extracted the features. Can some one help with this for loop please. I mean how to use subplot command and how to store each figure in loop.
Regards
path=glob.glob('the path having four wav files/*.wav')
for p in path:
y, sr = librosa.load(p, sr=16000)
mfcc=librosa.feature.mfcc(y)
S = librosa.feature.melspectrogram(y, sr)
fig, ax = plt.subplot(4,3,.....)
librosa.display.waveplot(y, sr=sr)
librosa.display.specshow(librosa.power_to_db(S, ref=np.max))
librosa.display.specshow(mfcc, x_axis="time",y_axis="mel")
plt.show()

import matplotlib.pyplot as plt
Arrays=np.random.rand(6,10,10)
N_figures=Arrays.shape[0]
for Id in range(1,N_figures+1):
Array=Arrays[Id-1]
plt.subplot(N_figures/2,N_figures/3,Id)
plt.imshow(Array)
You just need to change imshow with desired plottings. Since I don't have the spectrogram files I've used randomly created NumPy arrays. Your implementation doesn't work because fig, ax = plt.subplot(4,3,.....)
is not appropriate to use. Fig and axs returns in the function plt.subplots not plt.subplot.You can also use that method but outside of the for loop and then access the axs elements.

The final code is :
import matplotlib.pyplot as plt
import librosa
import librosa.display
import glob
path=glob.glob('E:/Python_On_All_Dataset/Four emotion_for plot/*.wav')
fig, ax = plt.subplots(nrows=4, ncols=3, sharex=True)
for i in range(4) :
y, sr = librosa.load(path[i], sr=16000)
librosa.display.waveplot(y, sr, ax=ax[i, 0]) # put wave in row i, column 0
plt.axis('off')
mfcc=librosa.feature.mfcc(y)
librosa.display.specshow(mfcc, x_axis='time', ax=ax[i, 1]) # mfcc in row i, column 1
S = librosa.feature.melspectrogram(y, sr)
librosa.display.specshow(librosa.power_to_db(S), x_axis='time', y_axis='log', ax=ax[i, 2]) # spectrogram in row i, column 2
Tried putting this axis(off after every plot, but somehow its not working)

Related

Plotting fuzzy data with matplotlib

I don't know where to start, as I think it is a new approach for me. Using matplotlib with python, I would like to plot a set of fuzzy numbers (for instance a set of triangular or bell curve fuzzy numbers) as in the picture below:
You can plot the curves recurrently. My try at reproducing your example (including the superposition of labels 1 and 6):
import matplotlib.pyplot as plt
import numpy as np
# creating the figure and axis
fig, ax = plt.subplots(1,1,constrained_layout=True)
# generic gaussian
y = np.linspace(-1,1,100)
x = np.exp(-5*y**2)
center_x = (0,2,4,1,3,0,5)
center_y = (6,2,3,4,5,6,7)
# loop for all the values
for i in range(len(center_x)):
x_c, y_c = center_x[i], center_y[i]
# plotting the several bells, relocated to (x_c, y_c)
ax.plot(x + x_c,y + y_c,
color='red',linewidth=2.0)
ax.plot(x_c,y_c,
'o',color='blue',markersize=3)
# adding label
ax.annotate(
str(i+1),
(x_c - 0.1,y_c), # slight shift in x
horizontalalignment='right',
verticalalignment='center',
color='blue',
)
ax.grid()
Every call to ax.plot() is adding points or curves (to be more precise, Artists) to the same axis. The same for ax.annotate() to create the labels.

Matplotlib margins/padding when using limits

I'm trying to set xlimits and keep the margins.
In a simplified code, the dataset contains 50 values. When plotting the whole data set, it is fine. However, I only want to plot values 20-40. The plot starts and ends without having any margins.
How do I plot values 20-40 but keep the margins?
Online I found to ways to play with the margin/padding
1) plt.tight_layout(pad=1.08, h_pad=None, w_pad=None, rect=None)
2) ax1.margins(0.05)
Both, however, do not seem to work when using xlimits.
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(1, 200, 50)
y = np.random.random(len(x))
fig_1 = plt.figure(figsize=(8, 4))
ax1 = plt.subplot(1,1,1)
ax1.plot(x, y)
ax1.set_xlim(x[19], x[40])
# ax1.plot(x[19:40], y[19:40])
# would create exactly the plot I want. But it is not the solution I am looking for.
# I cannot change/slice the data. I want to change the figure.

changing the size of subplots with matplotlib

I am trying to plot multiple rgb images with matplotlib
the code I am using is:
import numpy as np
import matplotlib.pyplot as plt
for i in range(0, images):
test = np.random.rand(1080, 720,3)
plt.subplot(images,2,i+1)
plt.imshow(test, interpolation='none')
the subplots appear tiny though as thumbnails
How can I make them bigger?
I have seen solutions using
fig, ax = plt.subplots()
syntax before but not with plt.subplot ?
plt.subplots initiates a subplot grid, while plt.subplot adds a subplot. So the difference is whether you want to initiate you plot right away or fill it over time. Since it seems, that you know how many images to plot beforehand, I would also recommend going with subplots.
Also notice, that the way you use plt.subplot you generate empy subplots in between the ones you are actually using, which is another reason they are so small.
import numpy as np
import matplotlib.pyplot as plt
images = 4
fig, axes = plt.subplots(images, 1, # Puts subplots in the axes variable
figsize=(4, 10), # Use figsize to set the size of the whole plot
dpi=200, # Further refine size with dpi setting
tight_layout=True) # Makes enough room between plots for labels
for i, ax in enumerate(axes):
y = np.random.randn(512, 512)
ax.imshow(y)
ax.set_title(str(i), fontweight='bold')

Stacking multiple plots on a 2Y axis

I am trying to plot multiple plots in a 2Y plot.
I have the following code:
Has a list of files to get some data;
Gets the x and y components of data to plot in y-axis 1 and y-axis 2;
Plots data.
When the loop iterates, it plots on different figures. I would like to get all the plots in the same figure.
Can anyone give me some help on this?
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
file=[list of paths]
for i in files:
# Loads Data from an excel file
data = pd.read_excel(files[i],sheet_name='Results',dtype=float)
# Gets x and y data from the loaded files
x=data.iloc[:,-3]
y1=data.iloc[:,-2]
y12=data.iloc[:,-1]
y2=data.iloc[:,3]
fig1=plt.figure()
ax1 = fig1.add_subplot(111)
ax1.set_xlabel=('x')
ax1.set_ylabel=('y')
ax1.plot(x,y1)
ax1.semilogy(x,y12)
ax2 = ax1.twinx() # instantiate a second axes that shares the same x-axis
ax2.plot(x,y2)
fig1.tight_layout()
plt.show()
You should instantiate the figure outside the loop, and then add the subplots while iterating. In this way you will have a single figure and all the plots inside it.
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
files=[list of paths]
fig1=plt.figure()
for i in files:
# Loads Data from an excel file
data = pd.read_excel(files[i],sheet_name='Results',dtype=float)
# Gets x and y data from the loaded files
x=data.iloc[:,-3]
y1=data.iloc[:,-2]
y12=data.iloc[:,-1]
y2=data.iloc[:,3]
ax1 = fig1.add_subplot(111)
ax1.set_xlabel=('x')
ax1.set_ylabel=('y')
ax1.plot(x,y1)
ax1.semilogy(x,y12)
ax2 = ax1.twinx() # instantiate a second axes that shares the same x-axis
ax2.plot(x,y2)
fig1.tight_layout()
plt.show()

Matplotlib plotting a single line that continuously changes color

I would like to plot a curve in the (x,y) plane, where the color of the curve depends on a value of another variable T. x is a 1D numpy array, y is a 1D numpy array.
T=np.linspace(0,1,np.size(x))**2
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(x,y)
I want the line to change from blue to red (using RdBu colormap) depending on the value of T (one value of T exists for every (x,y) pair).
I found this, but I don't know how to warp it to my simple example. How would I use the linecollection for my example? http://matplotlib.org/examples/pylab_examples/multicolored_line.html
Thanks.
One idea could be to set the color using color=(R,G,B) then split your plot into n segments and continuously vary either one of the R, G or B (or a combinations)
import pylab as plt
import numpy as np
# Make some data
n=1000
x=np.linspace(0,100,n)
y=np.sin(x)
# Your coloring array
T=np.linspace(0,1,np.size(x))**2
fig = plt.figure()
ax = fig.add_subplot(111)
# Segment plot and color depending on T
s = 10 # Segment length
for i in range(0,n-s,s):
ax.plot(x[i:i+s+1],y[i:i+s+1],color=(0.0,0.5,T[i]))
Hope this is helpful