やりたいこと
pyqtgraph内で右クリックしてPlot Options -> Transformsと進むとグラフの表示形式を変更してくれます。
環境
Mac OS
Python 3.8.5
PyQt5 5.15.2
PyQt5-sip 12.8.1
pyqtgraph 0.11.1
pip install PyQt5 PyQt5-sip pyqtgraph
コード
プロット用にnumpyを使用しています。 pip install numpy
"""pyqtgraphのPlot Options -> Transformsをリンクさせる"""
import dataclasses
import itertools
from typing import Optional
import sys
import numpy as np
from PyQt5 import QtWidgets # ほぼ使わない
import pyqtgraph as pg
SAMPLE_DATA1 = np.linspace(-100, 100) ** 2
SAMPLE_DATA2 = np.linspace(-100, 100) ** 3
@dataclasses.dataclass
class GraphLinkWidget(pg.GraphicsLayoutWidget):
"""メイン画面
Attributes #
----------
parent: Optional[QtWidgets.QWidget] default=None
親画面
"""
parent: Optional[QtWidgets.QWidget] = None
def __post_init__(self) -> None:
"""スーパークラス読み込みとプロット追加"""
super(GraphLinkWidget, self).__init__(parent=self.parent)
self.plotter1 = self.addPlot(row=0, col=0)
self.plotter1.showGrid(x=True, y=True, alpha=0.8)
self.plotter1_curve = self.plotter1.plot(pen=pg.mkPen('#f00', width=5)) # 線色:赤, 幅:5
self.plotter1_curve.setData(SAMPLE_DATA1)
self.plotter2 = self.addPlot(row=0, col=1)
self.plotter2.showGrid(x=True, y=True, alpha=0.8)
self.plotter2_curve = self.plotter2.plot(pen=pg.mkPen('#00f', width=5))
self.plotter2_curve.setData(SAMPLE_DATA2)
self.connect_slot()
def connect_slot(self) -> None:
"""スロット接続
itertools.permutationsは順列を作成してくれる関数
ex) list(itertools.permutations([1, 2, 3]))
>> [(0, 1, 2), (0, 2, 1), (1, 0, 2), (1, 2, 0), (2, 0, 1), (2, 1, 0)]
"""
for plot1, plot2 in itertools.permutations([self.plotter1, self.plotter2]):
plot1.ctrl.fftCheck.toggled.connect(plot2.ctrl.fftCheck.setChecked)
plot1.ctrl.logXCheck.toggled.connect(plot2.ctrl.logXCheck.setChecked)
plot1.ctrl.logYCheck.toggled.connect(plot2.ctrl.logYCheck.setChecked)
plot1.ctrl.derivativeCheck.toggled.connect(plot2.ctrl.derivativeCheck.setChecked)
plot1.ctrl.phasemapCheck.toggled.connect(plot2.ctrl.phasemapCheck.setChecked)
def main():
app = QtWidgets.QApplication(sys.argv)
window = GraphLinkWidget(parent=None)
window.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
詳細
以下でリンクさせています
def connect_slot(self) -> None:
"""スロット接続
itertools.permutationsは順列を作成してくれる関数
ex) list(itertools.permutations([1, 2, 3]))
>> [(0, 1, 2), (0, 2, 1), (1, 0, 2), (1, 2, 0), (2, 0, 1), (2, 1, 0)]
"""
for plot1, plot2 in itertools.permutations([self.plotter1, self.plotter2]):
plot1.ctrl.fftCheck.toggled.connect(plot2.ctrl.fftCheck.setChecked)
plot1.ctrl.logXCheck.toggled.connect(plot2.ctrl.logXCheck.setChecked)
plot1.ctrl.logYCheck.toggled.connect(plot2.ctrl.logYCheck.setChecked)
plot1.ctrl.derivativeCheck.toggled.connect(plot2.ctrl.derivativeCheck.setChecked)
plot1.ctrl.phasemapCheck.toggled.connect(plot2.ctrl.phasemapCheck.setChecked)
plot1.ctrl.logXCheck.toggled.connect(plot2.ctrl.logXCheck.setChecked)
例えば上記の場合、片方のグラフ(plot1)のlogXチェクボックスが押されたらもう片方(plot2)のlogXチェックボックスにもチェックをいれてリンクさせています。
self,plotter1, self.plotter2はPlotItemという型です。pg.PlotWidgetでグラフを作成した場合はgetPlotItem()
で取得できます。
class 'pyqtgraph.graphicsItems.PlotItem.PlotItem.PlotItem'
PlotWidgetの場合
plotter = pg.PlotWidget()
plotitem = plotter1.getPlotItem()
応用
"""GUIのボタンからグラフ表示を変更する"""
import dataclasses
from typing import Optional
import sys
import numpy as np
from PyQt5 import QtWidgets
import pyqtgraph as pg
SAMPLE_DATA1 = np.linspace(-10, 10) ** 2
SAMPLE_DATA2 = 2 * np.linspace(-10, 10) ** 2
@dataclasses.dataclass
class PlotLinkWindow(QtWidgets.QWidget):
"""メイン画面
Attributes #
----------
parent: Optional[QtWidgets.QWidget] default=None
親画面
"""
parent: Optional[QtWidgets.QWidget] = None
def __post_init__(self) -> None:
"""スーパークラス読み込みとウィジット作成"""
super(PlotLinkWindow, self).__init__(parent=self.parent)
self.setGeometry(100, 100, 800, 500)
self.setWindowTitle('PlotLinkWindow')
self.create_widgets()
self.create_layouts()
self.set_layouts()
self.connect_slot()
def create_widgets(self) -> None:
"""ウィジット作成"""
# toggle buttons
self.fft_btn = QtWidgets.QPushButton('FFT')
self.fft_btn.setCheckable(True)
self.logX_btn = QtWidgets.QPushButton('logX')
self.logX_btn.setCheckable(True)
self.logY_btn = QtWidgets.QPushButton('logY')
self.logY_btn.setCheckable(True)
self.derivative_btn = QtWidgets.QPushButton('dy/dx')
self.derivative_btn.setCheckable(True)
self.phasemap_btn = QtWidgets.QPushButton("Y' vs Y")
self.phasemap_btn.setCheckable(True)
# graph
self.plotter1 = pg.PlotWidget()
self.plotter1.showGrid(x=True, y=True, alpha=0.8)
self.plotter1_curve1 = self.plotter1.plot(pen=pg.mkPen('#f00', width=5))
self.plotter1_curve2 = self.plotter1.plot(pen=pg.mkPen('#0f0', width=5))
self.plotter1_curve1.setData(SAMPLE_DATA1)
self.plotter1_curve2.setData(SAMPLE_DATA2)
self.plotitem = self.plotter1.getPlotItem()
def create_layouts(self) -> None:
"""レイアウト作成"""
self.main_layout = QtWidgets.QHBoxLayout()
self.button_layout = QtWidgets.QVBoxLayout()
def set_layouts(self) -> None:
"""ウィジットをレイアウトにセット"""
self.main_layout.addLayout(self.button_layout)
self.main_layout.addWidget(self.plotter1)
self.button_layout.addWidget(self.fft_btn)
self.button_layout.addWidget(self.logX_btn)
self.button_layout.addWidget(self.logY_btn)
self.button_layout.addWidget(self.derivative_btn)
self.button_layout.addWidget(self.phasemap_btn)
self.setLayout(self.main_layout)
def connect_slot(self) -> None:
"""スロット接続"""
self.fft_btn.clicked.connect(lambda: self.plotitem.ctrl.fftCheck.setChecked(self.fft_btn.isChecked()))
self.logX_btn.clicked.connect(lambda: self.plotitem.ctrl.logXCheck.setChecked(self.logX_btn.isChecked()))
self.logY_btn.clicked.connect(lambda: self.plotitem.ctrl.logYCheck.setChecked(self.logY_btn.isChecked()))
self.derivative_btn.clicked.connect(
lambda: self.plotitem.ctrl.derivativeCheck.setChecked(self.derivative_btn.isChecked()))
self.phasemap_btn.clicked.connect(
lambda: self.plotitem.ctrl.phasemapCheck.setChecked(self.phasemap_btn.isChecked()))
def main():
app = QtWidgets.QApplication(sys.argv)
window = PlotLinkWindow()
window.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
参考
pyqtgraph、リンク軸間のトラックログ/リニア軸変換の違い
pyqtgraph.graphicsItems.PlotItem.PlotItem — pyqtgraph 0.11.1.dev0 documentation
この辺り
self.ctrl = c = Ui_Form()
...
c.fftCheck.toggled.connect(self.updateSpectrumMode)
c.logXCheck.toggled.connect(self.updateLogMode)
c.logYCheck.toggled.connect(self.updateLogMode)
c.derivativeCheck.toggled.connect(self.updateDerivativeMode)
c.phasemapCheck.toggled.connect(self.updatePhasemapMode)
itertools
すごいぞitertoolsくん - Qiita