previous question (link)
Here i want that when i move the scroll bar using mouse it will not scroll the graph but when i leave the mouse then the graph will be updated. Here every time axis limit are updating but i want it will update the axis limit when i leave the mouse moving the scroll bar at a certain position. Note : Here y -axis trick label position will be fixed and it would be visible but value will update when i scroll the graph.and i also want that scroll bar will start from right position.
Here my program :
import sys
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
import matplotlib.pyplot as plt
from matplotlib.figure import Figure
from PyQt5.QtWidgets import QMainWindow,QVBoxLayout
from PyQt5.QtWidgets import QApplication
from PyQt5 import QtCore, QtGui, QtWidgets
import datetime
from matplotlib.dates import num2date, date2num
from mpl_finance import candlestick_ochl as candlestick
import numpy as np
import matplotlib.ticker as ticker
import matplotlib.dates as mdates
import pylab as pl
class MainWindow_code_serarch(object):
def setup_code_serarch(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1070, 680)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayoutWidget1 = QtWidgets.QWidget(self.centralwidget)
self.verticalLayoutWidget1.setGeometry(QtCore.QRect(17, 30, 741, 13))
self.verticalLayoutWidget1.setObjectName("verticalLayoutWidget")
self.verticalLayout1 = QtWidgets.QVBoxLayout(self.verticalLayoutWidget1)
self.verticalLayout1.setContentsMargins(0, 0, 0, 0)
self.verticalLayout1.setObjectName("verticalLayout1")
self.verticalLayoutWidget = QtWidgets.QWidget(self.centralwidget)
self.verticalLayoutWidget.setGeometry(QtCore.QRect(17, 10, 1040, 603))
self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setObjectName("verticalLayout")
self.figure = Figure(figsize=(100,7.2), dpi=80, facecolor='k')
self.canvas = FigureCanvas(self.figure)
self.canvas.draw()
# self.widget = QtWidgets.QWidget()
# self.scroll_area = QtWidgets.QScrollArea(self.widget)
# self.scroll_area.setWidget(self.canvas)
# self.verticalLayout.addWidget(self.scroll_area)
self.scroll = QtWidgets.QScrollBar(QtCore.Qt.Horizontal)
self.axes, self.axes2 = self.figure.subplots(nrows=2, sharex=True)
self.verticalLayout.addWidget(self.canvas)
self.verticalLayout.addWidget(self.scroll)
data = {
'date': ['2018/10/29','2018/10/30', '2018/11/03', '2018/11/04', '2018/11/05', '2018/11/07', '2018/11/10', '2018/11/11','2018/11/12','2018/11/13'],
'open': [8824,8824, 8726.31, 8642.14, 8531.51, 8630.25, 8602.50, 8640.22,8202.50, 8610.22],
'high': [8858,8858, 8748.60, 8551.36, 8653.16, 8476.69, 8630, 8570.56 ,8602.50, 8640.22],
'low': [8688,8688, 8743.67, 8550.76, 8449.50, 8631.83, 8602.18, 8743.22 ,8502.50, 8540.22],
'close': [8820,8820, 8747.17, 8550.52, 8553., 8517.10, 8628.78, 8588.52 ,8602.50, 8640.22],
'volume': [17759.56,17759.56, 120000.17, 18739.52, 38599.50, 16517.10, 17723.78, 15588.52 ,28602.50, 28640.22]
}
x = date2num([datetime.datetime.strptime(d, '%Y/%m/%d').date() for d in data['date']])
t= np.arange(len(data['date']))
candle_trace = zip(t, data['open'], data['high'], data['low'], data['close'], data['volume'])
candlestick(self.axes, candle_trace, width=.75, colorup='g', colordown='r')
self.axes2.plot(t, [1, 2, 3, 4, 7, 8, 9,6,6,9])
self.axes.set_position([0.02, 0.37, 0.88, 0.6])
self.axes2.set_position([0.02, 0.15, 0.88, 0.22])
self.axes.tick_params(axis='both', color='#ffffff', labelcolor='#ffffff')
self.axes.yaxis.tick_right()
self.axes2.tick_params(axis='both', color='#ffffff', labelcolor='#ffffff')
self.axes2.grid(color='lightgray', linewidth=.5, linestyle=':')
self.axes.grid(color='lightgray', linewidth=.5, linestyle=':')
self.axes2.yaxis.tick_right()
self.axes.autoscale_view()
self.axes2.autoscale_view()
self.axes.set_facecolor('#041105')
self.axes2.set_facecolor('#041105')
# N = len(dates)
self.axes.set_xticks(range(0, len((x)), 1))
self.axes.set_xticklabels([mdates.num2date(d).strftime('%b-%d') for d in x])
self.axes.set_xticklabels([mdates.num2date(d).strftime('%Y-%m-%d') for d in x])
self.axes2.set_xticklabels([mdates.num2date(d).strftime('%Y-%m-%d') for d in x])
self.canvas.draw()
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 246, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
# self.pushButton.clicked.connect(self.graphShowCode)
self.step = .1
self.setupSlider()
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
# self.pushButton.setText(_translate("MainWindow", "OK"))
def setupSlider(self):
self.lims = np.array(self.axes2.get_xlim())
print("limit"+str(self.lims))
self.scroll.setPageStep(self.step * 100)
self.scroll.actionTriggered.connect(self.update)
self.update()
def update(self, evt=None):
r = self.scroll.value() / ((1 + self.step) * 100)
l1 = self.lims[0] + r * np.diff(self.lims)
l2 = l1 + np.diff(self.lims) * self.step
self.axes2.set_xlim(l1, l2)
self.axes.set_xlim(l1, l2)
print(self.scroll.value(), l1, l2)
self.figure.canvas.draw_idle()
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = MainWindow_code_serarch()
ui.setup_code_serarch(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
QScrollBar inherits a comprehensive set of signals from QAbstractSlider.
I have used sliderReleased(). because it is emit when the user releases the slider.To start scroll bar from right position. I initiate scroll bar value (99) Because here i find scroll bar minimal value is (0) and maximum value is (99).
my program :
import sys
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
import matplotlib.pyplot as plt
from matplotlib.figure import Figure
from PyQt5.QtWidgets import QMainWindow,QVBoxLayout
from PyQt5.QtWidgets import QApplication
from PyQt5 import QtCore, QtGui, QtWidgets
import datetime
from matplotlib.dates import num2date, date2num
from mpl_finance import candlestick_ochl as candlestick
import numpy as np
import matplotlib.ticker as ticker
import matplotlib.dates as mdates
import pylab as pl
class MainWindow_code_serarch(object):
def setup_code_serarch(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1070, 680)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayoutWidget1 = QtWidgets.QWidget(self.centralwidget)
self.verticalLayoutWidget1.setGeometry(QtCore.QRect(17, 30, 741, 13))
self.verticalLayoutWidget1.setObjectName("verticalLayoutWidget")
self.verticalLayout1 = QtWidgets.QVBoxLayout(self.verticalLayoutWidget1)
self.verticalLayout1.setContentsMargins(0, 0, 0, 0)
self.verticalLayout1.setObjectName("verticalLayout1")
self.verticalLayoutWidget = QtWidgets.QWidget(self.centralwidget)
self.verticalLayoutWidget.setGeometry(QtCore.QRect(17, 10, 1040, 603))
self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setObjectName("verticalLayout")
self.figure = Figure(figsize=(100,7.2), dpi=80, facecolor='k')
self.canvas = FigureCanvas(self.figure)
self.canvas.draw()
# self.widget = QtWidgets.QWidget()
# self.scroll_area = QtWidgets.QScrollArea(self.widget)
# self.scroll_area.setWidget(self.canvas)
# self.verticalLayout.addWidget(self.scroll_area)
self.scroll = QtWidgets.QScrollBar(QtCore.Qt.Horizontal)
self.axes, self.axes2 = self.figure.subplots(nrows=2, sharex=True)
self.verticalLayout.addWidget(self.canvas)
self.verticalLayout.addWidget(self.scroll)
self.scroll.setValue(99)
data = {
'date': ['2018/10/29','2018/10/30', '2018/11/03', '2018/11/04', '2018/11/05', '2018/11/07', '2018/11/10', '2018/11/11','2018/11/12','2018/11/13'],
'open': [8824,8824, 8726.31, 8642.14, 8531.51, 8630.25, 8602.50, 8640.22,8202.50, 8610.22],
'high': [8858,8858, 8748.60, 8551.36, 8653.16, 8476.69, 8630, 8570.56 ,8602.50, 8640.22],
'low': [8688,8688, 8743.67, 8550.76, 8449.50, 8631.83, 8602.18, 8743.22 ,8502.50, 8540.22],
'close': [8820,8820, 8747.17, 8550.52, 8553., 8517.10, 8628.78, 8588.52 ,8602.50, 8640.22],
'volume': [17759.56,17759.56, 120000.17, 18739.52, 38599.50, 16517.10, 17723.78, 15588.52 ,28602.50, 28640.22]
}
x = date2num([datetime.datetime.strptime(d, '%Y/%m/%d').date() for d in data['date']])
t= np.arange(len(data['date']))
candle_trace = zip(t, data['open'], data['high'], data['low'], data['close'], data['volume'])
candlestick(self.axes, candle_trace, width=.75, colorup='g', colordown='r')
self.axes2.plot(t, [1, 2, 3, 4, 7, 8, 9,6,6,9])
self.axes.set_position([0.02, 0.37, 0.88, 0.6])
self.axes2.set_position([0.02, 0.15, 0.88, 0.22])
self.axes.tick_params(axis='both', color='#ffffff', labelcolor='#ffffff')
self.axes.yaxis.tick_right()
self.axes2.tick_params(axis='both', color='#ffffff', labelcolor='#ffffff')
self.axes2.grid(color='lightgray', linewidth=.5, linestyle=':')
self.axes.grid(color='lightgray', linewidth=.5, linestyle=':')
self.axes2.yaxis.tick_right()
self.axes.autoscale_view()
self.axes2.autoscale_view()
self.axes.set_facecolor('#041105')
self.axes2.set_facecolor('#041105')
# N = len(dates)
self.axes.set_xticks(range(0, len((x)), 1))
self.axes.set_xticklabels([mdates.num2date(d).strftime('%b-%d') for d in x])
self.axes.set_xticklabels([mdates.num2date(d).strftime('%Y-%m-%d') for d in x])
self.axes2.set_xticklabels([mdates.num2date(d).strftime('%Y-%m-%d') for d in x])
self.canvas.draw()
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 246, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
# self.pushButton.clicked.connect(self.graphShowCode)
self.step = .1
self.setupSlider()
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
# self.pushButton.setText(_translate("MainWindow", "OK"))
def setupSlider(self):
self.lims = np.array(self.axes2.get_xlim())
print("limit"+str(self.lims))
self.scroll.setPageStep(self.step * 100)
# self.scroll.actionTriggered.connect(self.update)
self.scroll.sliderReleased.connect(self.update)
self.update()
def update(self, evt=None):
r = self.scroll.value() / ((1 + self.step) * 100)
l1 = self.lims[0] + r * np.diff(self.lims)
l2 = l1 + np.diff(self.lims) * self.step
self.axes2.set_xlim(l1, l2)
self.axes.set_xlim(l1, l2)
print(self.scroll.value(), l1, l2)
self.figure.canvas.draw_idle()
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = MainWindow_code_serarch()
ui.setup_code_serarch(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
Related
I am trying to plot microphone speech (real time) with python and matplotlib.
Here is what i have done:
file:chart_1.py
# -*- coding: utf-8 -*-
from PyQt5 import QtCore, QtGui, QtWidgets
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib import dates as mpl_dates
from matplotlib.animation import FuncAnimation
from pydub import AudioSegment
import numpy as np
import datetime
import pyaudio
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
# constants
self.CHUNK = int(16384/4)
self.CHUNK_TIME = 125 #msec
self.FORMAT = pyaudio.paInt16
self.CHANNELS = 1
self.RATE = 32750
self.p = pyaudio.PyAudio()
MainWindow.setObjectName("MainWindow")
MainWindow.resize(630, 200)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth())
MainWindow.setSizePolicy(sizePolicy)
MainWindow.setMinimumSize(QtCore.QSize(0, 200))
MainWindow.setMaximumSize(QtCore.QSize(16777215, 200))
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setSpacing(0)
self.verticalLayout.setObjectName("verticalLayout")
MainWindow.setCentralWidget(self.centralwidget)
self.chart = Canvas(self)
self.chart.ax.set_facecolor((1,1,1))
self.chart.ax.tick_params(labelcolor='white')
self.stream = self.p.open(format=self.FORMAT,channels=self.CHANNELS,rate=self.RATE,input=True,output=True,frames_per_buffer=self.CHUNK)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "Microphone chart"))
def plot_microphone_data(self):
now = datetime.datetime.now()
self.x_vals = []
self.y_vals = []
while(True):
data = self.stream.read(self.CHUNK)
#slice = AudioSegment(data, sample_width=2, frame_rate=self.RATE, channels=1)
#print(len(slice))
#print(len(slice.raw_data))
self.stream.write(data)
audio_data = np.frombuffer(data, np.int16)
self.chart.li.set_xdata(np.arange(len(audio_data)))
self.chart.li.set_ydata(audio_data)
self.chart.fig.canvas.draw()
self.chart.fig.canvas.flush_events()
class Canvas(FigureCanvas):
def __init__(self,parent):
self.fig , self.ax = plt.subplots(figsize=(5,4),dpi=200)
self.fig.patch.set_facecolor((6/255,21/255,154/255))
self.ax.set_position([0., 0, 1., 0.8])
self.ax.xaxis.tick_top()
self.ax.tick_params(color=(1,1,1))
super().__init__(self.fig)
parent.verticalLayout.addWidget(self)
plt.cla()
plt.xticks(fontsize=5)
self.ax.grid(False)
self.li, = self.ax.plot([], [])
self.ax.set_xlim(0,1000)
self.ax.set_ylim(-8000,8000)
self.show()
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
ui.plot_microphone_data()
sys.exit(app.exec_())
works well, but it hasn't time in x axis so i have made the file chart_2.py
# -*- coding: utf-8 -*-
from PyQt5 import QtCore, QtGui, QtWidgets
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib import dates as mpl_dates
from matplotlib.animation import FuncAnimation
from pydub import AudioSegment
import numpy as np
import datetime
import pyaudio
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
# constants
self.CHUNK = int(16384/4)
self.CHUNK_TIME = 125 #msec
self.FORMAT = pyaudio.paInt16
self.CHANNELS = 1
self.RATE = 32750
self.TIME_WINDOW = 3000 #display 3 seconds on chart
self.p = pyaudio.PyAudio()
MainWindow.setObjectName("MainWindow")
MainWindow.resize(630, 200)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(MainWindow.sizePolicy().hasHeightForWidth())
MainWindow.setSizePolicy(sizePolicy)
MainWindow.setMinimumSize(QtCore.QSize(0, 200))
MainWindow.setMaximumSize(QtCore.QSize(16777215, 200))
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setSpacing(0)
self.verticalLayout.setObjectName("verticalLayout")
MainWindow.setCentralWidget(self.centralwidget)
self.chart = Canvas(self)
self.chart.ax.set_facecolor((1,1,1))
self.chart.ax.tick_params(labelcolor='white')
self.stream = self.p.open(format=self.FORMAT,channels=self.CHANNELS,rate=self.RATE,input=True,output=True,frames_per_buffer=self.CHUNK,stream_callback=self.microphone_callback)
self.x_vals = np.array([])
self.y_vals = np.array([])
self.now = datetime.datetime.now()
self.stream.start_stream()
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "Microphone chart"))
def microphone_callback(self,in_data, frame_count, time_info, status):
data = in_data
#slice = AudioSegment(data, sample_width=2, frame_rate=self.RATE, channels=1)
#print(len(slice))
#print(len(slice.raw_data))
audio_data = np.frombuffer(data, np.int16)
time_data = np.array([])
for i in range(0,len(audio_data)):
time_data = np.append(time_data, self.now)
self.now = self.now+datetime.timedelta(milliseconds=self.CHUNK_TIME/len(audio_data))
self.x_vals = np.concatenate((self.x_vals, time_data), axis=0)
self.y_vals = np.concatenate((self.y_vals, audio_data), axis=0)
if(self.x_vals.size>audio_data.size*(self.TIME_WINDOW/self.CHUNK_TIME)):
self.x_vals = self.x_vals[audio_data.size:]
self.y_vals = self.y_vals[audio_data.size:]
self.chart.li.set_xdata(self.x_vals)
self.chart.li.set_ydata(self.y_vals)
x_ticks = []
for i in range(0,self.TIME_WINDOW+1,1000):
tick = self.x_vals[0]+datetime.timedelta(milliseconds=i)
x_ticks.append(tick)
plt.xticks(x_ticks)
self.chart.ax.set_xlim(x_ticks[0],x_ticks[-1])
self.chart.fig.canvas.draw()
self.chart.fig.canvas.flush_events()
return (data, pyaudio.paContinue)
class Canvas(FigureCanvas):
def __init__(self,parent):
self.fig , self.ax = plt.subplots(figsize=(5,4),dpi=200)
self.fig.patch.set_facecolor((6/255,21/255,154/255))
self.ax.set_position([0., 0, 1., 0.8])
self.ax.xaxis.tick_top()
self.ax.tick_params(color=(1,1,1))
super().__init__(self.fig)
parent.verticalLayout.addWidget(self)
self.now = datetime.datetime.now()
self.chart_stop = self.now+datetime.timedelta(milliseconds=parent.TIME_WINDOW)
plt.cla()
date_format = mpl_dates.DateFormatter("%H:%M:%S")
plt.gca().xaxis.set_major_formatter(date_format)
plt.xticks(fontsize=5)
self.ax.grid(False)
self.li, = self.ax.plot([], [])
self.ax.set_ylim(-8000,8000)
x_ticks = []
for i in range(0,parent.TIME_WINDOW+1,1000):
tick = self.now+datetime.timedelta(milliseconds=i)
x_ticks.append(tick)
plt.xticks(x_ticks)
self.ax.set_xlim(x_ticks[0],x_ticks[-1])
self.show()
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
Chart 2 has time on upper x axis but it has some delay problems.
Can you please advice me to fix that?
in my program i have taken figure first then i import figue into canvas. Then i import canvas into scroll area. when i run my program ,then if i turn left scroll the yaxis tick label goes hide or i turn right scroll the yaxis tick label goes also hide.
i have taken two axis. axis,axis2. i have set axes2.yaxis.tick_right() and axes.yaxis.tick_right().
I want that the yaxis tick label will stay at right side and alyas visible, whatever i turn scroll left or right .
import sys
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
import matplotlib.pyplot as plt
from matplotlib.figure import Figure
from PyQt5.QtWidgets import QMainWindow,QVBoxLayout
from PyQt5.QtWidgets import QApplication
from PyQt5 import QtCore, QtGui, QtWidgets
import datetime
from matplotlib.dates import num2date, date2num
from mpl_finance import candlestick_ochl as candlestick
import numpy as np
import matplotlib.ticker as ticker
import matplotlib.dates as mdates
import pylab as pl
class MainWindow_code_serarch(object):
def setup_code_serarch(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(870, 680)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayoutWidget1 = QtWidgets.QWidget(self.centralwidget)
self.verticalLayoutWidget1.setGeometry(QtCore.QRect(17, 30, 741, 13))
self.verticalLayoutWidget1.setObjectName("verticalLayoutWidget")
self.verticalLayout1 = QtWidgets.QVBoxLayout(self.verticalLayoutWidget1)
self.verticalLayout1.setContentsMargins(0, 0, 0, 0)
self.verticalLayout1.setObjectName("verticalLayout1")
self.verticalLayoutWidget = QtWidgets.QWidget(self.centralwidget)
self.verticalLayoutWidget.setGeometry(QtCore.QRect(17, 10, 940, 603))
self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setObjectName("verticalLayout")
self.figure = Figure(figsize=(100,7.2), dpi=80, facecolor='k')
self.canvas = FigureCanvas(self.figure)
self.widget = QtWidgets.QWidget()
self.scroll_area = QtWidgets.QScrollArea(self.widget)
self.scroll_area.setWidget(self.canvas)
self.verticalLayout.addWidget(self.scroll_area)
axes,axes2 = self.figure.subplots(nrows=2, sharex=True)
data = {
'date': ['2018/10/30', '2018/11/03', '2018/11/04', '2018/11/05', '2018/11/07', '2018/11/10', '2018/11/11'],
'open': [8824, 8726.31, 8642.14, 8531.51, 8630.25, 8602.50, 8640.22],
'high': [8858, 8748.60, 8551.36, 8653.16, 8476.69, 8630, 8570.56],
'low': [8688, 8743.67, 8550.76, 8449.50, 8631.83, 8602.18, 8743.22],
'close': [8820, 8747.17, 8550.52, 8553., 8517.10, 8628.78, 8588.52],
'volume': [17759.56, 120000.17, 18739.52, 38599.50, 16517.10, 17723.78, 15588.52]
}
x = date2num([datetime.datetime.strptime(d, '%Y/%m/%d').date() for d in data['date']])
t= np.arange(len(data['date']))
candle_trace = zip(t, data['open'], data['high'], data['low'], data['close'], data['volume'])
candlestick(axes, candle_trace, width=.75, colorup='g', colordown='r')
axes2.plot(t, [1, 2, 3, 4, 7, 8, 9])
axes.set_position([0.02, 0.37, 0.88, 0.6])
axes2.set_position([0.02, 0.15, 0.88, 0.22])
axes.tick_params(axis='both', color='#ffffff', labelcolor='#ffffff')
axes.yaxis.tick_right()
axes2.tick_params(axis='both', color='#ffffff', labelcolor='#ffffff')
axes2.grid(color='lightgray', linewidth=.5, linestyle=':')
axes.grid(color='lightgray', linewidth=.5, linestyle=':')
axes2.yaxis.tick_right()
axes.autoscale_view()
axes2.autoscale_view()
axes.set_facecolor('#041105')
axes2.set_facecolor('#041105')
# N = len(dates)
axes.set_xticks(range(0, len((x)), 1))
axes.set_xticklabels([mdates.num2date(d).strftime('%b-%d') for d in x])
axes.set_xticklabels([mdates.num2date(d).strftime('%Y-%m-%d') for d in x])
axes2.set_xticklabels([mdates.num2date(d).strftime('%Y-%m-%d') for d in x])
self.canvas.draw()
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 246, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
# self.pushButton.clicked.connect(self.graphShowCode)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
# self.pushButton.setText(_translate("MainWindow", "OK"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = MainWindow_code_serarch()
ui.setup_code_serarch(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
Output image:
when i turn scroll left output image 2:
Here is a way to scroll the content of an axes with a PyQt QtScrollBar. This is done by changing the limits of the axes depending on the scroll bar's value. To this end, a callback to the QtScrollBar's actionTriggered method is registered that changes the limits of the axes.
import sys
import matplotlib
# Make sure that we are using QT5
matplotlib.use('Qt5Agg')
import matplotlib.pyplot as plt
from PyQt5 import QtWidgets, QtCore
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
import numpy as np
class ScrollableWindow(QtWidgets.QMainWindow):
def __init__(self, fig, ax, step=0.1):
plt.close("all")
if not QtWidgets.QApplication.instance():
self.app = QtWidgets.QApplication(sys.argv)
else:
self.app = QtWidgets.QApplication.instance()
QtWidgets.QMainWindow.__init__(self)
self.widget = QtWidgets.QWidget()
self.setCentralWidget(self.widget)
self.widget.setLayout(QtWidgets.QVBoxLayout())
self.widget.layout().setContentsMargins(0,0,0,0)
self.widget.layout().setSpacing(0)
self.fig = fig
self.ax = ax
self.canvas = FigureCanvas(self.fig)
self.canvas.draw()
self.scroll = QtWidgets.QScrollBar(QtCore.Qt.Horizontal)
self.step = step
self.setupSlider()
self.nav = NavigationToolbar(self.canvas, self.widget)
self.widget.layout().addWidget(self.nav)
self.widget.layout().addWidget(self.canvas)
self.widget.layout().addWidget(self.scroll)
self.canvas.draw()
self.show()
self.app.exec_()
def setupSlider(self):
self.lims = np.array(self.ax.get_xlim())
self.scroll.setPageStep(self.step*100)
self.scroll.actionTriggered.connect(self.update)
self.update()
def update(self, evt=None):
r = self.scroll.value()/((1+self.step)*100)
l1 = self.lims[0]+r*np.diff(self.lims)
l2 = l1 + np.diff(self.lims)*self.step
self.ax.set_xlim(l1,l2)
print(self.scroll.value(), l1,l2)
self.fig.canvas.draw_idle()
# create a figure and some subplots
fig, ax = plt.subplots()
t = np.linspace(0,3000,101)
x = np.cumsum(np.random.randn(len(t)))
ax.plot(t,x, marker="o")
# pass the figure to the custom window
a = ScrollableWindow(fig,ax)
For a Scrollbar within the figure, see Scrollable Bar graph matplotlib
The above answer works well, but does not hand back control to the spyder window or python command line. Also in spyder it could be run only once. Added a few more points seen from another thread on exiting from QT window and improved to this.
import sys
import matplotlib
# Make sure that we are using QT5
matplotlib.use('Qt5Agg')
import matplotlib.pyplot as plt
from PyQt5 import QtWidgets, QtCore
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
import numpy as np
from PyQt5.QtWidgets import QMainWindow, QLabel, QGridLayout, QWidget
from PyQt5.QtCore import QSize
class HelloWindow(QMainWindow):
def __init__(self, fig, ax , step = 0.1):
plt.close("all")
if not QtWidgets.QApplication.instance():
self.app = QtWidgets.QApplication(sys.argv)
else:
self.app = QtWidgets.QApplication.instance()
QMainWindow.__init__(self)
self.setMinimumSize(QSize(1500, 100))
self.setWindowTitle("Value Plotting")
self.step = step
self.widget = QWidget()
self.setCentralWidget( self.widget )
self.widget.setLayout(QtWidgets.QVBoxLayout())
self.widget.layout().setContentsMargins(0,0,0,0)
self.widget.layout().setSpacing(0)
self.fig = fig
self.ax = ax
self.canvas = FigureCanvas(self.fig)
self.canvas.draw()
self.scroll = QtWidgets.QScrollBar(QtCore.Qt.Horizontal)
self.step = step
self.setupSlider()
self.nav = NavigationToolbar(self.canvas, self.widget)# self.widget.layout().addWidget(self.nav)
self.widget.layout().addWidget(self.canvas)
self.widget.layout().addWidget(self.scroll)
menu = self.menuBar().addMenu('Action for quit')
action = menu.addAction('Quit')
action.triggered.connect(QtWidgets.QApplication.quit)
self.canvas.draw()
def setupSlider(self):
self.lims = np.array(self.ax.get_xlim())
self.scroll.setPageStep(self.step*100)
self.scroll.actionTriggered.connect(self.update)
self.update()
def update(self, evt=None):
r = self.scroll.value()/((1+self.step)*100)
l1 = self.lims[0]+r*np.diff(self.lims)
l2 = l1 + np.diff(self.lims)*self.step
self.ax.set_xlim(l1,l2)
print(self.scroll.value(), l1,l2)
self.fig.canvas.draw_idle()
if __name__ == "__main__":
def run_app(fig,ax):
app = QtWidgets.QApplication(sys.argv)
mainWin = HelloWindow(fig,ax)
mainWin.show()
app.exec_()
fig, ax = plt.subplots()
t = np.linspace(0,3000,101)
x = np.cumsum(np.random.randn(len(t)))
ax.plot(t,x, marker="o")
run_app(fig,ax)
Found it running well on the python console. Exiting roughly in Spyder. Top close button not working, but exiting when operating from menu.
I am currently building a GUI using pyqt, does anyone know how I can align a qtexttable and a qimage next to each other in a qtextdocument. They are presently stacked but I would prefer if they can be inserted side by side. Please find below my code. The table and image are both embedded in the qtextdocument.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib qt5
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(QtWidgets.QWidget):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout.setObjectName("gridLayout")
self.scrollArea = QtWidgets.QScrollArea(self.centralwidget)
self.scrollArea.setWidgetResizable(True)
self.scrollArea.setObjectName("scrollArea")
self.scrollAreaWidgetContents = QtWidgets.QWidget()
self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 780, 533))
self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents")
self.gridLayout_2 = QtWidgets.QGridLayout(self.scrollAreaWidgetContents)
self.gridLayout_2.setContentsMargins(0, 0, 0, 0)
self.gridLayout_2.setObjectName("gridLayout_2")
self.textEdit = QtWidgets.QTextEdit(self.scrollAreaWidgetContents)
self.textEdit.setObjectName("textEdit")
self.textEdit.setReadOnly(True)
self.textEdit.setAcceptRichText(True)
document = QtGui.QTextDocument()
self.textEdit.setDocument(document)
self.gridLayout_2.addWidget(self.textEdit, 0, 0, 1, 1)
self.figure = Figure()
self.canvas = FigureCanvas(self.figure)
self.pushButton = QtWidgets.QPushButton(self.scrollAreaWidgetContents)
self.pushButton.setObjectName("pushButton")
self.pushButton.clicked.connect(self.vis_plot)
self.gridLayout_2.addWidget(self.pushButton, 1, 0, 1, 1)
self.scrollArea.setWidget(self.scrollAreaWidgetContents)
self.gridLayout.addWidget(self.scrollArea, 0, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 25))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.pushButton.setText(_translate("MainWindow", "PushButton"))
def vis_plot(self):
df = pd.DataFrame(np.random.randn(100,4),columns = list('ABCD'))
ax1 = self.figure.add_subplot(111)
for column in df:
col = pd.DataFrame(df[column])
col_stat = col.apply([np.min, np.max, np.mean, np.median])
col_table = col_stat.rename(index={'amin':'Minimum', 'amax':'Maximum','mean':'Mean', 'median':'Median'})
col_table.reset_index(level=0, inplace=True)
col_tablerender = col_table.rename(columns={col_table.columns[0]:'Metric', col_table.columns[1]:'Value'})
cursor = self.textEdit.textCursor()
cursor.insertTable(len(col_tablerender), 2)
for id, value in col_tablerender.iterrows():
for row in value:
cursor.insertText(str(row))
cursor.movePosition(QtGui.QTextCursor.NextCell)
col.plot.hist(ax=ax1, title=str(column))
self.canvas.draw()
size = self.canvas.size()
width, height = size.width(), size.height()
im = QtGui.QImage(self.canvas.buffer_rgba(), width, height, QtGui.QImage.Format_ARGB32)
cursor = self.textEdit.textCursor()
cursor.insertImage(im)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
I would prefer something that looks like this
I try to add the datacursor functionality to my bar chart by using the following code:
datacursor(hover=True, formatter=self.formatter)
No error happens but tooltip doesn't show when I hover my mouse pointer over a bar.
I try to put the following code (and this one works perfectly) into a QWidget:
import numpy as np
import matplotlib.pyplot as plt
from mpldatacursor import datacursor
label = ['a', 'b', 'c', 'd']
x = [1, 2, 3, 4]
y = [10, 20, 30, 40]
fig, ax = plt.subplots()
ax.bar(x, y, align='center', color='lightblue')
ax.margins(0.05)
ax.set_ylim(bottom=0)
def formatter(**kwargs):
dist = abs(np.array(x) - kwargs['x'])
i = dist.argmin()
return '\n'.join(label[i])
datacursor(hover=True, formatter=formatter)
plt.show()
Here my current code.
back_end:
from PyQt5 import QtCore, QtGui, QtWidgets
import sys
from PyQt5.QtWidgets import QMainWindow, QApplication, QWidget
from front_end import Ui_MainWindow
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
import matplotlib.pyplot as plt
from mpldatacursor import datacursor
class Ui_MainWindow(QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(Ui_MainWindow, self).__init__(parent)
self.setupUi(self)
self.graph = MyCanvas()
self.gridLayout.addWidget(self.graph, 0, 0, 1, 1)
self.populate()
def populate(self):
self.graph.figure.clf()
self.axes= self.graph.figure.add_subplot(111)
label = ['a', 'b', 'c', 'd']
x = [1, 2, 3, 4]
y = [10, 20, 30, 40]
datacursor(hover=True, formatter=self.formatter)
self.axes.bar(x, y, align='center', bottom=0, color='b')
def formatter(**kwargs):
x = [1, 2, 3, 4]
dist = abs(np.array(x) - kwargs['x'])
i = dist.argmin()
return '\n'.join(label[i])
class MyCanvas(FigureCanvas):
def __init__(self, *args, **kwargs):
self.figure = plt.figure()
FigureCanvas.__init__(self, self.figure)
self.figure.patch.set_facecolor("None")
self.figure.subplots_adjust(left=0.08, bottom=0.10, right=0.99, top=0.97)
if __name__ == '__main__':
app = QApplication(sys.argv)
prog = Ui_MainWindow()
prog.show()
sys.exit(app.exec_())
front_end:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(625, 460)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout.setObjectName("gridLayout")
self.widget = QtWidgets.QWidget(self.centralwidget)
self.widget.setObjectName("widget")
self.gridLayout.addWidget(self.widget, 0, 0, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 625, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
There are several issues.
x and label that are used inside of the formatter method need to be defined. A good solution would be to make them class variables.
The formatter method should be a method of the class. Hence it would best be defined as one by using the self argument.
Naming the class in use the same as an imported class may lead to confusion, best name it differently.
The datacursor needs to know which objects to work on, hence one would need to first define the bar plot and later call the datacursor function with those bars as argument.
There is no need to join anything on the return of the formatter, just return the label to show.
This should then look like
class MyWindow(QMainWindow, Ui_MainWindow):
# ....
def populate(self):
self.graph.figure.clf()
self.axes= self.graph.figure.add_subplot(111)
self.label = ['a', 'b', 'c', 'd']
self.x = [1, 2, 3, 4]
self.y = [10, 20, 30, 40]
bars = self.axes.bar(self.x, self.y, align='center', bottom=0, color='b')
datacursor(bars, hover=True, formatter=self.formatter)
def formatter(self, **kwargs):
dist = abs(np.array(self.x) - kwargs['x'])
i = dist.argmin()
return self.label[i]
I tried to integrate the code of this Radar graphic (see link) into a GUI containing a widget.
Instead of plotting x and y into the widget, I would like to plot a radar graphic but I can't solve this problem.
The idea is to replace this piece of code:
x = [2000,2001,2002,2003,2004]
y = [10,20,30,40,50]
self.axes.plot(x, y
With the code from the link above.
Below the code of the back end of my GUI:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QMainWindow, QApplication, QWidget, QSizePolicy
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure
from front_end import Ui_MainWindow
class Graph_init(FigureCanvas):
def __init__(self, parent=None):
fig = Figure()
self.axes = fig.add_subplot(111)
self.compute_initial_figure()
FigureCanvas.__init__(self, fig)
self.setParent(parent)
FigureCanvas.setSizePolicy(self, QSizePolicy.Expanding, QSizePolicy.Expanding)
FigureCanvas.updateGeometry(self)
class Graph_populate(Graph_init):
def compute_initial_figure(self):
x = [2000,2001,2002,2003,2004]
y = [10,20,30,40,50]
self.axes.plot(x, y)
class GUI(QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(GUI, self).__init__(parent)
self.setupUi(self)
self.sc = Graph_populate(self.widget)
self.gridLayout.addWidget(self.sc, 0, 1, 1, 1)
if __name__ == '__main__':
app = QApplication(sys.argv)
prog = GUI()
prog.showMaximized()
sys.exit(app.exec_())
and the front end:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(595, 393)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout.setObjectName("gridLayout")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setMaximumSize(QtCore.QSize(100, 16777215))
self.pushButton.setObjectName("pushButton")
self.gridLayout.addWidget(self.pushButton, 0, 0, 1, 1)
self.widget = QtWidgets.QWidget(self.centralwidget)
self.widget.setMinimumSize(QtCore.QSize(0, 200))
self.widget.setStyleSheet("background-color: rgb(255, 255, 255);")
self.widget.setObjectName("widget")
self.gridLayout.addWidget(self.widget, 0, 1, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 595, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.pushButton.setText(_translate("MainWindow", "PushButton"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
Thank you
the radar type graph is a graph with polar projection, so when creating the axes you must activate that property.
self.axes = fig.add_subplot(111, projection="polar")
When using the plot function, the first parameter is the angle in radians, and the second the length of the radius.
class Graph_init(FigureCanvas):
def __init__(self, parent=None):
fig = Figure()
self.axes = fig.add_subplot(111, projection="polar")
self.compute_initial_figure()
FigureCanvas.__init__(self, fig)
self.setParent(parent)
FigureCanvas.setSizePolicy(self, QSizePolicy.Expanding, QSizePolicy.Expanding)
FigureCanvas.updateGeometry(self)
class Graph_populate(Graph_init):
def compute_initial_figure(self):
import math
r =[10, 20, 30, 40, 50]
theta = [0, 50, 90, 120, 180]
angles = [angle*math.pi/180 for angle in theta]
self.axes.plot(angles, r)