Pyside6: Dynamically add points to chart view - python

I want to make an application that put a random point on a graph every 5 seconds but it does not update when I append the point to the line series. I also tried the repaint() and QApplication.ProcessEvent() but still does not update.
here's my code
import random
from PySide6 import QtCore, QtWidgets
from PySide6.QtCharts import QChartView, QChart, QLineSeries
class MyGraph(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.points = []
# Set up the graph
self.point_line_series = QLineSeries()
self.chart = QChart()
self.chart.addSeries(self.point_line_series)
self.chart.setTitle("Points Over Time")
self.chart_view = QChartView()
self.chart_view.setChart(self.chart)
self.setCentralWidget(self.chart_view)
# Start a timer to add new points every 5 seconds
self.timer = QtCore.QTimer()
self.timer.timeout.connect(self.add_point)
self.timer.start(5000)
def add_point(self):
x = random.randint(0, 100)
y = random.randint(0, 100)
self.points.append((x, y))
self.point_line_series.append(x, y)
print(f"added point {x}, {y}")
self.repaint()
self.chart_view.repaint()
QtWidgets.QApplication.processEvents()
if __name__ == "__main__":
app = QtWidgets.QApplication()
graph = MyGraph()
graph.show()
app.exec_()
I want to add points every 5 seconds and update the graph.
The graph does not update but the points is appended to the line series.

here's the workaround
import random
from PySide6 import QtCore, QtWidgets
from PySide6.QtCharts import QChartView, QChart, QLineSeries
class MyGraph(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.points = []
# Set up the graph
self.point_line_series = QLineSeries()
chart = QChart()
chart.addSeries(self.point_line_series)
chart.setTitle("Points Over Time")
self.chart_view = QChartView()
self.chart_view.setChart(chart)
self.setCentralWidget(self.chart_view)
# Start a timer to add new points every 5 seconds
self.timer = QtCore.QTimer()
self.timer.timeout.connect(self.add_point)
self.timer.start(5000)
def add_point(self):
x = random.randint(0, 100)
y = random.randint(0, 100)
self.points.append((x, y))
self.point_line_series.append(x, y)
print(f"added point {x}, {y}")
chart = QChart()
chart.addSeries(self.point_line_series)
self.chart_view.setChart(chart)
if __name__ == "__main__":
app = QtWidgets.QApplication()
graph = MyGraph()
graph.show()
app.exec_()
basically just make a new chart add the line series and set that chart as the chart of chart view using chart.setchart()

Related

Add custom label inside PlotWidget

I'm trying to add a label to the top right corner of the plot showing the most recent data value. I've tried using pg.LabelItem and adding this to pg.PlotWidget and updating the label with each new data update but I'm unable to get the label to appear. Here's some pictures of what I'm trying to do:
What I have:
What I'm trying to do:
I can't get the white label to appear on the plot. Here's my code:
from PyQt4 import QtCore, QtGui
from threading import Thread
import pyqtgraph as pg
import numpy as np
import random
import sys
import time
class SimplePlot(QtGui.QWidget):
def __init__(self, parent=None):
super(SimplePlot, self).__init__(parent)
# Desired Frequency (Hz) = 1 / self.FREQUENCY
# USE FOR TIME.SLEEP (s)
self.FREQUENCY = .004
# Frequency to update plot (ms)
# USE FOR TIMER.TIMER (ms)
self.TIMER_FREQUENCY = self.FREQUENCY * 1000
# Set X Axis range. If desired is [-10,0] then set LEFT_X = -10 and RIGHT_X = 0
self.LEFT_X = -10
self.RIGHT_X = 0
self.X_Axis = np.arange(self.LEFT_X, self.RIGHT_X, self.FREQUENCY)
self.buffer = int((abs(self.LEFT_X) + abs(self.RIGHT_X))/self.FREQUENCY)
self.data = []
# Create Plot Widget
self.simple_plot_widget = pg.PlotWidget()
# Enable/disable plot squeeze (Fixed axis movement)
self.simple_plot_widget.plotItem.setMouseEnabled(x=False, y=False)
self.simple_plot_widget.setXRange(self.LEFT_X, self.RIGHT_X)
self.simple_plot_widget.setTitle('Plot')
self.simple_plot_widget.setLabel('left', 'Value')
self.simple_plot_widget.setLabel('bottom', 'Time (s)')
self.simple_plot = self.simple_plot_widget.plot()
self.simple_plot.setPen(197,235,255)
self.label_value = pg.LabelItem('', **{'color': '#FFF'})
self.simple_plot_widget.addItem(self.label_value)
self.layout = QtGui.QGridLayout()
self.layout.addWidget(self.simple_plot_widget)
self.read_position_thread()
self.start()
# Update plot
def start(self):
self.position_update_timer = QtCore.QTimer()
self.position_update_timer.timeout.connect(self.plot_updater)
self.position_update_timer.start(self.get_simple_plot_timer_frequency())
# Read in data using a thread
def read_position_thread(self):
self.current_position_value = 0
self.old_current_position_value = 0
self.position_update_thread = Thread(target=self.read_position, args=())
self.position_update_thread.daemon = True
self.position_update_thread.start()
def read_position(self):
frequency = self.get_simple_plot_frequency()
while True:
try:
# Add data
self.current_position_value = self.current_position_value + random.uniform(-1, -5)
self.old_current_position_value = self.current_position_value
time.sleep(frequency)
except:
self.current_position_value = self.old_current_position_value
def plot_updater(self):
self.dataPoint = float(self.current_position_value)
if len(self.data) >= self.buffer:
del self.data[:1]
self.data.append(self.dataPoint)
self.simple_plot.setData(self.X_Axis[len(self.X_Axis) - len(self.data):], self.data)
# Update label value
self.label_value.setText(str(self.dataPoint))
def clear_simple_plot(self):
self.data[:] = []
def get_simple_plot_frequency(self):
return self.FREQUENCY
def get_simple_plot_timer_frequency(self):
return self.TIMER_FREQUENCY
def get_simple_plot_layout(self):
return self.layout
def get_current_position_value(self):
return self.current_position_value
def get_simple_plot_widget(self):
return self.simple_plot_widget
if __name__ == '__main__':
app = QtGui.QApplication([])
mw = QtGui.QMainWindow()
mw.setWindowTitle('Plot')
simple_plot_widget = SimplePlot()
cw = QtGui.QWidget()
ml = QtGui.QGridLayout()
cw.setLayout(ml)
mw.setCentralWidget(cw)
ml.addLayout(simple_plot_widget.get_simple_plot_layout(),0,0)
mw.show()
# Start Qt event loop unless running in interactive mode or using pyside
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
It may be because your plot is rescaling constantly, and the size of the LabelItem doesn't change with it, also it seems to be positioned on the positive side of the x-axis, so you cant visualize the text.
Pyqtgraph recommends here to use TextItem instead of LabelItem, to display text inside a scaled view.
I tried using the TextItem and it worked fine, but its default position is bad, maybe because your plot is in the negative quadrant. Just use the setPos() method like this:
# Update label value
self.label_value.setPos(QtCore.QPointF(-9, 0.6*min(self.data)))
self.label_value.setText(str(self.dataPoint))
And it should do what you want.

Remove / Delete Legend in PyQtGraph

Two lines are created on the live chart and a legend is added. At the next update, the lines on the chart are deleted using self.pw.clear().
But the legend is not deleted, and with each update, a new instance of the legend is added, there are a lot of them and the FPS of the schedule update quickly drops.
Here http://www.pyqtgraph.org/documentation/graphicsItems/plotitem.html says Clear(): “Remove all items from the ViewBox.”
Attempting to Clear / removeItem - have not yet helped (either the syntax is incorrect, or the procedure call is incorrect).
How to delete a legend when updating a chart or stop multiple legends creation?
import random
from PyQt5 import QtGui
import pyqtgraph as pg
import sys
class Mainwindow(QtGui.QMainWindow):
def __init__(self, parent):
super(Mainwindow, self).__init__()
self.centralWidget = QtGui.QWidget()
self.setCentralWidget(self.centralWidget)
self.resize(1000, 500)
self.vbox = QtGui.QVBoxLayout()
self.pw = pg.PlotWidget()
self.vbox.addWidget(self.pw)
self.centralWidget.setLayout(self.vbox)
# Update chart
self.timer = pg.QtCore.QTimer()
self.timer.setSingleShot(False)
self.timer.timeout.connect(self.update)
self.timer.start(10)
def update(self):
x = []
y = []
z = []
for i in range(10000):
x.append(i)
y.append(random.uniform(0, 1))
z.append(1 + random.uniform(0, 1))
self.pw.clear()
line_red = pg.PlotCurveItem(x, y, clear=True, pen='r', name='Red')
line_yellow = pg.PlotCurveItem(x, z, clear=True, pen='y', name='Yellow')
self.pw.addItem(line_red)
self.pw.addItem(line_yellow)
self.pw.addLegend()
app = QtGui.QApplication(sys.argv)
ex = Mainwindow(app)
ex.show()
sys.exit(app.exec_())
You have an XY problem, instead of asking How to update the plot? questions How to eliminate the duplicate legend ?. So I will point out a solution to the underlying problem.
Considering the above, the logic is to only create the items once and update the information using the setData() method.
import random
import sys
import pyqtgraph as pg
from pyqtgraph.Qt import QtGui
class Mainwindow(QtGui.QMainWindow):
def __init__(self, parent):
super(Mainwindow, self).__init__()
self.centralWidget = QtGui.QWidget()
self.setCentralWidget(self.centralWidget)
self.resize(1000, 500)
vbox = QtGui.QVBoxLayout(self.centralWidget)
self.pw = pg.PlotWidget()
self.pw.addLegend()
vbox.addWidget(self.pw)
# Update chart
self.timer = pg.QtCore.QTimer()
self.timer.setSingleShot(False)
self.timer.timeout.connect(self.update)
self.timer.start(10)
self.line_red = pg.PlotCurveItem(clear=True, pen="r", name="Red")
self.line_yellow = pg.PlotCurveItem(clear=True, pen="y", name="Yellow")
self.pw.addItem(self.line_red)
self.pw.addItem(self.line_yellow)
def update(self):
x = []
y = []
z = []
for i in range(10000):
x.append(i)
y.append(random.uniform(0, 1))
z.append(1 + random.uniform(0, 1))
self.line_red.setData(x, y)
self.line_yellow.setData(x, z)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
ex = Mainwindow(app)
ex.show()
sys.exit(app.exec_())

How to make the X-axis time dynamically refresh by using pyqtgraph TimeAxisItem

I'm going to make a real-time curve out of a sequence of data. First, I established a quantity dictionary, which has 3 groups of data. The current program can draw a curve dynamically. The X-axis can also show the time, which is also updated in real time. However, the time at different points in the X-axis is always the same value.
UNIX_EPOCH_naive = datetime.datetime(1970, 1, 1, 0, 0) #offset-naive datetime
UNIX_EPOCH_offset_aware = datetime.datetime(1970, 1, 1, 0, 0, tzinfo = pytz.utc) #offset-aware datetime
UNIX_EPOCH = UNIX_EPOCH_naive
TS_MULT_us = 1e6
def now_timestamp(ts_mult=TS_MULT_us, epoch=UNIX_EPOCH):
return(int((datetime.datetime.utcnow() - epoch).total_seconds()*ts_mult))
def int2dt(ts, ts_mult=TS_MULT_us):
tz = pytz.timezone('Asia/Shanghai')
user_ts = int(time.time())
d1 = datetime.datetime.fromtimestamp(float(user_ts))
d1x = tz.localize(d1)
return(d1x)
def dt2int(dt, ts_mult=TS_MULT_us, epoch=UNIX_EPOCH):
delta = dt - epoch
return(int(delta.total_seconds()*ts_mult))
def td2int(td, ts_mult=TS_MULT_us):
return(int(td.total_seconds()*ts_mult))
def int2td(ts, ts_mult=TS_MULT_us):
return(datetime.timedelta(seconds=float(ts)/ts_mult))
class TimeAxisItem(pg.AxisItem):
def __init__(self, *args, **kwargs):
super(TimeAxisItem, self).__init__(*args, **kwargs)
def tickStrings(self, values, scale, spacing):
return [int2dt(value).strftime("%H:%M:%S") for value in values]
p = win.addPlot(title="Data-Time Graph", axisItems={'bottom': TimeAxisItem(orientation='bottom')})
data_dict = {}
p.addLegend()
data_x=[]
def getDate():
......
.....
curve = p.plot(pen = color[len(data_dict)],name=name)
data_dict[name] = [curve] # dictionary: {key:[curve,[dadta1,data2,...]]}
data_dict[name].append([val])
def addToDisplay():
p.plot()
for i in data_dict.items():
data = i[1][1] #
curve = i[1][0] #
if(len(data) > data_frequency):#
data_y=data[- data_frequency:]
else:
data_y = data[:]
curve.setData(data_y)#
if __name__ == "__main__":
th= threading.Thread(target=getDate)#
th.start()
timer = pg.QtCore.QTimer()
timer.timeout.connect(addToDisplay)
timer.start(10)
What I hope is that the X-axis is dynamically refreshed, with the latest time on the right side and the past time is on the left side.
I'm not entirely sure what you're trying to achieve since your code doesn't run but it seems you're trying to create a timestamp plot. Here's a widget that uses TimeAxisItem to keep track of elapsed time on the X-axis.
PyQt5
from PyQt5 import QtCore, QtGui, QtWidgets
from threading import Thread
from collections import deque
import pyqtgraph as pg
import numpy as np
import random
import sys
import time
"""Scrolling Timestamp Plot Widget Example"""
class TimeAxisItem(pg.AxisItem):
"""Internal timestamp for x-axis"""
def __init__(self, *args, **kwargs):
super(TimeAxisItem, self).__init__(*args, **kwargs)
def tickStrings(self, values, scale, spacing):
"""Function overloading the weak default version to provide timestamp"""
return [QtCore.QTime().currentTime().addMSecs(value).toString('mm:ss') for value in values]
class ScrollingTimestampPlot(QtGui.QWidget):
"""Scrolling plot widget with timestamp on x-axis and dynamic y-axis"""
def __init__(self, parent=None):
super(ScrollingTimestampPlot, self).__init__(parent)
# Internal timestamp for x-axis
self.timestamp = QtCore.QTime()
self.timestamp.start()
# Desired Frequency (Hz) = 1 / self.FREQUENCY
# USE FOR TIME.SLEEP (s)
self.FREQUENCY = 0.025
# Screen refresh rate to update plot (ms)
# self.SCROLLING_TIMESTAMP_PLOT_REFRESH_RATE = 1 / Desired Frequency (Hz) * 1000
# USE FOR TIMER.TIMER (ms)
self.SCROLLING_TIMESTAMP_PLOT_REFRESH_RATE = self.FREQUENCY * 1000
self.DATA_POINTS_TO_DISPLAY = 200
# Automatically pops from left if length is full
self.data = deque(maxlen=self.DATA_POINTS_TO_DISPLAY)
# Create Plot Widget
self.scrolling_timestamp_plot_widget = pg.PlotWidget(axisItems={'bottom': TimeAxisItem(orientation='bottom')})
# Enable/disable plot squeeze (Fixed axis movement)
self.scrolling_timestamp_plot_widget.plotItem.setMouseEnabled(x=False, y=False)
self.scrolling_timestamp_plot_widget.setTitle('Scrolling Timestamp Plot Example')
self.scrolling_timestamp_plot_widget.setLabel('left', 'Value')
self.scrolling_timestamp_plot_widget.setLabel('bottom', 'Time (s)')
self.scrolling_timestamp_plot = self.scrolling_timestamp_plot_widget.plot()
self.scrolling_timestamp_plot.setPen(246,212,255)
self.layout = QtGui.QGridLayout()
self.layout.addWidget(self.scrolling_timestamp_plot_widget)
self.read_position_thread()
self.start()
def start(self):
"""Update plot"""
self.position_update_timer = QtCore.QTimer()
self.position_update_timer.timeout.connect(self.plot_updater)
self.position_update_timer.start(self.get_scrolling_timestamp_plot_refresh_rate())
def read_position_thread(self):
"""Read in data using a thread"""
self.current_position_value = 0
self.position_update_thread = Thread(target=self.read_position, args=())
self.position_update_thread.daemon = True
self.position_update_thread.start()
def read_position(self):
frequency = self.get_scrolling_timestamp_plot_frequency()
while True:
self.current_position_value = random.randint(1,101)
time.sleep(frequency)
def plot_updater(self):
self.data_point = float(self.current_position_value)
self.data.append({'x': self.timestamp.elapsed(), 'y': self.data_point})
self.scrolling_timestamp_plot.setData(x=[item['x'] for item in self.data], y=[item['y'] for item in self.data])
def clear_scrolling_timestamp_plot(self):
self.data.clear()
def get_scrolling_timestamp_plot_frequency(self):
return self.FREQUENCY
def get_scrolling_timestamp_plot_refresh_rate(self):
return self.SCROLLING_TIMESTAMP_PLOT_REFRESH_RATE
def get_scrolling_timestamp_plot_layout(self):
return self.layout
def get_current_position_value(self):
return self.current_position_value
def get_scrolling_timestamp_plot_widget(self):
return self.scrolling_timestamp_plot_widget
# Start Qt event loop unless running in interactive mode or using pyside
if __name__ == '__main__':
# Create main application window
app = QtWidgets.QApplication([])
app.setStyle(QtGui.QStyleFactory.create("Cleanlooks"))
mw = QtGui.QMainWindow()
mw.setWindowTitle('Scrolling Plot Example')
# Create scrolling plot
scrolling_timestamp_plot_widget = ScrollingTimestampPlot()
# Create and set widget layout
# Main widget container
cw = QtGui.QWidget()
ml = QtGui.QGridLayout()
cw.setLayout(ml)
mw.setCentralWidget(cw)
# Can use either to add plot to main layout
#ml.addWidget(scrolling_timestamp_plot_widget.get_scrolling_timestamp_plot_widget(),0,0)
ml.addLayout(scrolling_timestamp_plot_widget.get_scrolling_timestamp_plot_layout(),0,0)
mw.show()
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()
PyQt4
from PyQt4 import QtCore, QtGui
from threading import Thread
from collections import deque
import pyqtgraph as pg
import numpy as np
import random
import sys
import time
"""Scrolling Timestamp Plot Widget Example"""
class TimeAxisItem(pg.AxisItem):
"""Internal timestamp for x-axis"""
def __init__(self, *args, **kwargs):
super(TimeAxisItem, self).__init__(*args, **kwargs)
def tickStrings(self, values, scale, spacing):
"""Function overloading the weak default version to provide timestamp"""
return [QtCore.QTime().addMSecs(value).toString('mm:ss') for value in values]
class ScrollingTimestampPlot(QtGui.QWidget):
"""Scrolling plot widget with timestamp on x-axis and dynamic y-axis"""
def __init__(self, parent=None):
super(ScrollingTimestampPlot, self).__init__(parent)
# Internal timestamp for x-axis
self.timestamp = QtCore.QTime()
self.timestamp.start()
# Desired Frequency (Hz) = 1 / self.FREQUENCY
# USE FOR TIME.SLEEP (s)
self.FREQUENCY = 0.025
# Screen refresh rate to update plot (ms)
# self.SCROLLING_TIMESTAMP_PLOT_REFRESH_RATE = 1 / Desired Frequency (Hz) * 1000
# USE FOR TIMER.TIMER (ms)
self.SCROLLING_TIMESTAMP_PLOT_REFRESH_RATE = self.FREQUENCY * 1000
self.DATA_POINTS_TO_DISPLAY = 200
# Automatically pops from left if length is full
self.data = deque(maxlen=self.DATA_POINTS_TO_DISPLAY)
# Create Plot Widget
self.scrolling_timestamp_plot_widget = pg.PlotWidget(axisItems={'bottom': TimeAxisItem(orientation='bottom')})
# Enable/disable plot squeeze (Fixed axis movement)
self.scrolling_timestamp_plot_widget.plotItem.setMouseEnabled(x=False, y=False)
self.scrolling_timestamp_plot_widget.setTitle('Scrolling Timestamp Plot Example')
self.scrolling_timestamp_plot_widget.setLabel('left', 'Value')
self.scrolling_timestamp_plot_widget.setLabel('bottom', 'Time (s)')
self.scrolling_timestamp_plot = self.scrolling_timestamp_plot_widget.plot()
self.scrolling_timestamp_plot.setPen(246,212,255)
self.layout = QtGui.QGridLayout()
self.layout.addWidget(self.scrolling_timestamp_plot_widget)
self.read_position_thread()
self.start()
def start(self):
"""Update plot"""
self.position_update_timer = QtCore.QTimer()
self.position_update_timer.timeout.connect(self.plot_updater)
self.position_update_timer.start(self.get_scrolling_timestamp_plot_refresh_rate())
def read_position_thread(self):
"""Read in data using a thread"""
self.current_position_value = 0
self.position_update_thread = Thread(target=self.read_position, args=())
self.position_update_thread.daemon = True
self.position_update_thread.start()
def read_position(self):
frequency = self.get_scrolling_timestamp_plot_frequency()
while True:
self.current_position_value = random.randint(1,101)
time.sleep(frequency)
def plot_updater(self):
self.data_point = float(self.current_position_value)
self.data.append({'x': self.timestamp.elapsed(), 'y': self.data_point})
self.scrolling_timestamp_plot.setData(x=[item['x'] for item in self.data], y=[item['y'] for item in self.data])
def clear_scrolling_timestamp_plot(self):
self.data.clear()
def get_scrolling_timestamp_plot_frequency(self):
return self.FREQUENCY
def get_scrolling_timestamp_plot_refresh_rate(self):
return self.SCROLLING_TIMESTAMP_PLOT_REFRESH_RATE
def get_scrolling_timestamp_plot_layout(self):
return self.layout
def get_current_position_value(self):
return self.current_position_value
def get_scrolling_timestamp_plot_widget(self):
return self.scrolling_timestamp_plot_widget
# Start Qt event loop unless running in interactive mode or using pyside
if __name__ == '__main__':
# Create main application window
app = QtGui.QApplication([])
app.setStyle(QtGui.QStyleFactory.create("Cleanlooks"))
mw = QtGui.QMainWindow()
mw.setWindowTitle('Scrolling Plot Example')
# Create scrolling plot
scrolling_timestamp_plot_widget = ScrollingTimestampPlot()
# Create and set widget layout
# Main widget container
cw = QtGui.QWidget()
ml = QtGui.QGridLayout()
cw.setLayout(ml)
mw.setCentralWidget(cw)
# Can use either to add plot to main layout
#ml.addWidget(scrolling_timestamp_plot_widget.get_scrolling_timestamp_plot_widget(),0,0)
ml.addLayout(scrolling_timestamp_plot_widget.get_scrolling_timestamp_plot_layout(),0,0)
mw.show()
if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()

link auto-scale on multiple plots in pyqtgraph

Is it possible link the auto-scale of several plots?
I want to scale all the plots with which ever is the biggest range on all curves of all plots.
Is there way to make it with a pyqtgraph function, or should I find the max, min and set the scale with a custom function?
I am using pyqtgraph on PyQt5
Pyqtgraph should automatically scale the y-axis on multiple plots with which ever has the largest range. Here's an example widget with auto-scaling plots in PyQt4 but the concept should be the same for PyQt5.
import pyqtgraph as pg
from pyqtgraph.Qt import QtCore, QtGui
import numpy as np
import sys
import random
class AutoScaleMultiplePlotWidget(QtGui.QWidget):
def __init__(self, parent=None):
super(AutoScaleMultiplePlotWidget, self).__init__(parent)
self.NUMBER_OF_PLOTS = 4
self.LEFT_X = 0
self.RIGHT_X = 5
self.SPACING = 1
self.x_axis = np.arange(self.LEFT_X, self.RIGHT_X + 1, self.SPACING)
self.buffer_size = int((abs(self.LEFT_X) + abs(self.RIGHT_X) + 1)/self.SPACING)
self.auto_scale_plot_widget = pg.PlotWidget()
self.auto_scale_plot_widget.setLabel('left', 'left axis')
# Create plots
self.left_plot1 = self.auto_scale_plot_widget.plot()
self.left_plot2 = self.auto_scale_plot_widget.plot()
self.left_plot3 = self.auto_scale_plot_widget.plot()
self.left_plot4 = self.auto_scale_plot_widget.plot()
self.left_plot1.setPen((173,255,129), width=1)
self.left_plot2.setPen((172,187,255), width=1)
self.left_plot3.setPen((255,190,116), width=1)
self.left_plot4.setPen((204,120,255), width=1)
self.initialize_plot_buffers()
self.initialize_data_buffers()
self.layout = QtGui.QGridLayout()
self.layout.addWidget(self.auto_scale_plot_widget)
self.start()
def initialize_data_buffers(self):
"""Create blank data buffers for each curve"""
self.data_buffers = []
for trace in range(self.NUMBER_OF_PLOTS):
self.data_buffers.append([0])
def initialize_plot_buffers(self):
"""Add plots into buffer for each curve"""
self.plots = []
self.plots.append(self.left_plot1)
self.plots.append(self.left_plot2)
self.plots.append(self.left_plot3)
self.plots.append(self.left_plot4)
def update_plot(self):
"""Generates new random value and plots curve onto plot"""
for trace in range(self.NUMBER_OF_PLOTS):
if len(self.data_buffers[trace]) >= self.buffer_size:
self.data_buffers[trace].pop(0)
data_point = self.data_buffers[trace][-1] + random.randint(10,50)
self.data_buffers[trace].append(float(data_point))
self.plots[trace].setData(self.x_axis[len(self.x_axis) - len(self.data_buffers[trace]):], self.data_buffers[trace])
def get_auto_scale_plot_layout(self):
return self.layout
def start(self):
self.multiple_axis_plot_timer = QtCore.QTimer()
self.multiple_axis_plot_timer.timeout.connect(self.update_plot)
self.multiple_axis_plot_timer.start(500)
if __name__ == '__main__':
# Create main application window
app = QtGui.QApplication([])
app.setStyle(QtGui.QStyleFactory.create("Cleanlooks"))
mw = QtGui.QMainWindow()
mw.setWindowTitle('Auto Scale Multiple Plot Example')
# Create plot
auto_scale_plot = AutoScaleMultiplePlotWidget()
# Create and set widget layout
# Main widget container
cw = QtGui.QWidget()
ml = QtGui.QGridLayout()
cw.setLayout(ml)
mw.setCentralWidget(cw)
# Add plot to main layout
ml.addLayout(auto_scale_plot.get_auto_scale_plot_layout(),0,0)
mw.show()
if(sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
QtGui.QApplication.instance().exec_()

plot mutiple line on the same figure using mplwidget in python(x,y)

I was trying to plot multiple line/dots using the mplwidget in Qtdesigner plugin. Usually when i use matplotlib in python by default it will keep the first line graph and plot another graph on top of that for comparison. But in Qtdesigner,after i am using matplotlib as a widget object, i select figure object then addsubplot and then plot the graph, it seems like it will delete the old line graph and plot the new one. I'm pretty sure there's something wrong with the coding, but i'm new to this GUI stuff, i'm not sure which part of it went wrong
import sys
from PyQt4 import QtGui, QtCore
from window import Ui_MainWindow
import sqlite3
import os
from datetime import datetime
import calendar
import numpy
os.chdir("C:\Data")
conn = sqlite3.connect('FBG.db')
c=conn.cursor()
class Main(QtGui.QMainWindow):
def searching_database(self):
self.ui.listWidget.clear()
data = self.ui.Inputname.text()
for df in c.execute("select name from sqlite_master where type='table'; "):
strdf=str(df)
if len(data)==0:
break
if strdf[3:(len(data)+3)] == data: # the name for df start from position 3 due to "[u "
self.ui.listWidget.addItem(strdf[3:-3])
else:
pass
def delete_selection(self):
self.ui.listWidget_3.takeItem(self.ui.listWidget_3.currentRow())
def clear_graph(self):
self.ui.listWidget_3.clear()
self.ax.clear()
self.ui.mplwidget.draw()
def plot_graph(self):
b=self.ui.listWidget.currentItem().text()
b=str(b)
self.ui.listWidget_3.addItem(b)
time1= QtCore.QDateTime(self.ui.dateTimeEdit.dateTime())
date1 = time1.toPyDateTime()
timestamp1 = calendar.timegm(date1.utctimetuple()) #return a integer value
time2= QtCore.QDateTime(self.ui.dateTimeEdit_2.dateTime())
date2 = time2.toPyDateTime()
timestamp2 = calendar.timegm(date2.utctimetuple())
time=[]
data=[]
for df in c.execute('''select * from '''+ b ):
time= numpy.append(time, df[0])
data= numpy.append(data, df[1])
self.ax.plot([2,4,5,6],[1,5,6,7],label=b) % set up for matplot widget
self.ax.plot([1,3,4,5],[2,4,5,6],label=b+"afasdasdasd") % set up for matplot widget
self.ax.legend() % set up for matplot widget
self.ui.mplwidget.draw() % set up for matplot widget
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.ui.Inputname.textChanged.connect(self.searching_database)
self.ui.listWidget.itemDoubleClicked.connect(self.plot_graph)
self.ui.pushButton.clicked.connect(self.plot_graph)
self.ui.Delete.clicked.connect(self.delete_selection)
self.ui.Clear.clicked.connect(self.clear_graph)
self.ui.mplwidget.axes.set_title("Strain/Temperature vs Time") % set up for matplot widget
self.fig = self.ui.mplwidget.figure % set up for matplot widget
self.ax = self.fig.add_subplot(1,1,1) % set up for matplot widget
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window= Main()
window.show()
sys.exit(app.exec_())
The code is running fine. But i think there must be some code prevent me getting what i am trying to achieve. I think it might those codes with "% set up for matplot widget" following them. Any suggestions would be good.
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
class myWidget(QWidget):
def __init__(self, parent=None):
super(myWidget, self).__init__(parent)
self.fig = plt.figure()
self.canvas = FigureCanvas(self.fig)
self.vbox = QVBoxLayout()
self.vbox.addWidget(self.canvas)
self.setLayout(self.vbox)
self.plotCurve(self.canvas)
def plotCurve(self, FigureCanvas):
left, width = 0.1, 0.8
rect1 = [left, 0.2, width, 0.6]
FigureCanvas.figure.set_facecolor('white')
axescolor = '#f6f6f6' # the axies background color
FigureCanvas.figure.clear()
ax1 = FigureCanvas.figure.add_axes(rect1, axisbg=axescolor) #left, bottom, width, height
ax1.set_title('Some Curve')
x = range(10, 20)
y = range(10, 20)
z = range(20, 30)
p1, = ax1.plot(x, y, 'ro')
p2, = ax1.plot(x, z, '-')
ax1.set_ylabel('Some Label')
FigureCanvas.draw()
def main():
app = QApplication(sys.argv)
form = myWidget()
form.show()
app.exec_()
main()
Try this:
self.ui.mplwidget.axes.hold(True)
This should let you plot two data sets on the same axis, just like you can in interactive mode. Worked for me!

Categories