简体   繁体   中英

How to remove inner margins from Matplotlib plots?

I'm trying to plot an audio waveform using PyQt5 and Matplotlib, and despite trying several suggestions from other questions, I can't get the inner margins to disappear. I must be doing something wrong.

The audio waveform should be touching the edges of the widget, but as you can see in this screengrab, there is a large black inner margin on all four sides:

音频波形图在所有边都有大的边距

My code includes tight_layout() and subplots_adjust() calls from examples found online, but they don't seem to be having any effect. (The audio is maximised so the peak values should be hitting 100% of the available plot.)

Can somebody point out why the margins are still persisting please?

Full sample code:

import sys
import wave

import matplotlib as mpl
import numpy as np
from PyQt5 import QtCore
from PyQt5.QtWidgets import QApplication, QLabel
from PyQt5.QtWidgets import QDialog, QGridLayout
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure


class MatplotlibWidget(FigureCanvas):
    def __init__(self, parent=None):
        super(MatplotlibWidget, self).__init__(Figure())
        self.setParent(parent)

        self.figure = Figure(tight_layout=True)
        self.figure.tight_layout(pad=0)
        self.canvas = FigureCanvas(self.figure)
        self.plot = None

        self.figure.set_facecolor("black")
        mpl.rcParams["lines.linewidth"] = 1
        mpl.rcParams["lines.color"] = "b"

    def plotAudio(self, waveformData):
        self.plot = self.figure.add_subplot(111, position=[0, 0, 1, 1])
        self.plot.clear()
        self.plot.axis("off")
        self.plot.use_sticky_edges = True
        self.plot.set_title(None)
        self.plot.set_xlabel(None)
        self.plot.set_ylabel(None)
        self.plot.margins(0)
        self.figure.subplots_adjust(left=0, right=1, top=1, bottom=0, wspace=0, hspace=0)
        self.figure.tight_layout(pad=0)
        self.plot.plot(waveformData)
        self.canvas.draw()
        self.draw()


class WaveformTest(QDialog):
    def __init__(self):
        super().__init__()
        self.title = 'PyQt5 tests'
        self.setMinimumSize(200, 200)
        self.setWindowFlags(QtCore.Qt.Window |
                            QtCore.Qt.WindowTitleHint |
                            QtCore.Qt.WindowCloseButtonHint)

        self.label = QLabel("Waveform")
        self.waveformWidget = MatplotlibWidget()

        self.layout = QGridLayout(self)
        self.layout.addWidget(self.label, 0, 0)
        self.layout.addWidget(self.waveformWidget, 1, 0)

    def plotAudio(self, sourceFile):
        spf = wave.open(str(sourceFile), "r")
        signal = spf.readframes(-1)
        signal = np.fromstring(signal, "Int16")

        self.waveformWidget.plotAudio(signal)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = WaveformTest()
    ex.show()
    sourceFile = "C:\\temp\\937-01400_20200622091518.wav"
    ex.plotAudio(sourceFile)
    sys.exit(app.exec_())

You are creating a canvas inside the canvas unnecessarily, and that adds the margins. So the solution is to remove the unnecessary canvas:

class MatplotlibWidget(FigureCanvas):
    def __init__(self, parent=None):
        super(MatplotlibWidget, self).__init__(Figure())
        self.setParent(parent)
        self.figure.tight_layout(pad=0)
        self.plot = None

        self.figure.set_facecolor("black")
        mpl.rcParams["lines.linewidth"] = 1
        mpl.rcParams["lines.color"] = "b"

    def plotAudio(self, waveformData):
        self.plot = self.figure.add_subplot(111, position=[0, 0, 1, 1])
        self.plot.clear()
        self.plot.axis("off")
        self.plot.use_sticky_edges = True
        self.plot.set_title(None)
        self.plot.set_xlabel(None)
        self.plot.set_ylabel(None)
        self.plot.margins(0)
        self.figure.subplots_adjust(
            left=0, right=1, top=1, bottom=0, wspace=0, hspace=0
        )
        self.figure.tight_layout(pad=0)
        self.plot.plot(waveformData)
        self.draw()

Before

在此处输入图像描述

After

在此处输入图像描述

I think what you want to get might be obtained using the xlim and ylim methods inside your plotAudio function. Since I don't have your data set, I will show you its application in a hypothetical noisy function example:

import numpy as np
import matplotlib.pyplot as plt

num = np.random.uniform(-np.pi, np.pi, 10000)
sig = np.sin(num) + np.random.normal(0, 1, 10000)

figure = plt.Figure(tight_layout=True)

plot = figure.add_subplot(111, position=[0, 0, 1, 1])
plot.axis("off")
plot.use_sticky_edges = True

plot.set_title(None)
plot.set_xlabel(None)
plot.set_ylabel(None)

plot.margins(0)
figure.subplots_adjust(left=0, right=1, top=1, bottom=0, wspace=0, hspace=0)
figure.tight_layout(pad=0)

plt.xlim([-np.pi, np.pi])
plt.ylim([sig.min(), sig.max()])

plt.scatter(num, sig)
plt.show()

Here I include the plots with and without the explicit limits (basically commenting out the lines I added to your matplotlib code):

没有限制 有限制

I hope this gives you some hints.

Edit:

After debugging your code with the supplied input file, I found that something very close to the desired output can be found by modifying the MatplotlibWidget class like this:

class MatplotlibWidget(FigureCanvas):
    def __init__(self, parent=None):
        super(MatplotlibWidget, self).__init__(Figure())
        self.setParent(parent)

        self.figure = Figure(constrained_layout=True)
        self.figure.set_facecolor("black")
        self.canvas = FigureCanvas(self.figure)

        mpl.rcParams["lines.linewidth"] = 1
        mpl.rcParams["lines.color"] = "b"

    def plotAudio(self, waveformData):
        plot = self.figure.add_subplot(111)
        plot.margins(0)
        plot.axis("off")
        plot.plot(waveformData)

By setting the constrained_layout keyword argument one can obtain the following plot:

在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM