Issue
I am trying to plot temperature data points according to their time recording.
t = ['2021-12-11T0:6:15', '2021-12-11T7:15', '2021-12-11T8:15', '2021-12-11T9:15', '2021-12-11T10:15']
temp = [33.6, 33.6, 33.6, 33.6, 33.6]
Note: as you have mentioned t
is represented without hour
, the reason is that temp
been collected in hour:second
.
t
is a string representing the date and time in ISO 8601 format (ref: datetime.datetime.isoformat()) and temp
is a floating number. The plot should be in a way that t
in x-axis
(represented as hour:min) and temp
in y-axis
(represented in celcius). I want to keep the variables as lists and plot a graph without using Pandas but PyQtGraph library.
I tried the following:
from PySide6.QtWidgets import (
QApplication,
QMainWindow
)
import pyqtgraph as pg # import PyQtGraph after Qt
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.graphWidget = pg.PlotWidget()
self.setCentralWidget(self.graphWidget)
t = # declared above
temp = # declared above
# plot data: time, temp values
self.graphWidget.plot(time, temp)
# Always start by initializing Qt (only once per application)
app = QApplication([])
window = MainWindow()
## Display the widget as a new window
window.show()
## Start the Qt event loop
app.exec_()
After running the above code, I got a traceback:
numpy.core._exceptions._UFuncNoLoopError: ufunc 'fmin' did not contain a loop with signature matching types (dtype('<U18'), dtype('<U18')) -> None
I know that there is a problem with t
since its values are str
which they should be same type as of temp
(note: temp
values should always stay float
). I am not sure how to fix it.
I am using PySide6 and PyQtGraph, where Python is the language used. For this, I also tried to just plot the two variables using matplotlib
library. I did the following:
import numpy as np
import matplotlib.pyplot as plt
x, y = t, temp
plt.plot(x, y, label='temperature fluctuation')
plt.xlabel('time (hour:min)')
plt.ylabel('temperature (C)')
plt.legend(loc='lower right')
Solution
A few assumptions:
- You mean
hour:minutes
and nothour:seconds
as written. If differently, please clarify your point - The time string is wrong: according to ISO 8601 hours and minutes should be two-character string chunks. You have to first clean the string list. I've done it manually since a Python script for that is out-of-scope
- I've used a slight different
temp
array just for displaying some variability in the graph. Completely negligible
That said, the proposed way is:
- Convert the iso strings into timestamp (float) values. This will be handled by
pyqtgraph
to plot numbers. - Convert the full ISO strings into strings with format
HH:MM
as you require and that you'll use as axis ticks. You have two choices that are in-code explained (please, read comments) - Get the
x-axis
from thePlotWidget
and use thesetTick
property to set your custom ticks. To do so, you have to create a list of tuple with two values, the underlying numeric data and the custom string data
Here is the code:
from datetime import datetime
from PySide6.QtWidgets import (
QApplication,
QMainWindow
)
import pyqtgraph as pg # import PyQtGraph after Qt
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.graphWidget = pg.PlotWidget()
self.setCentralWidget(self.graphWidget)
t_string_list = ['2021-12-11T06:15', '2021-12-11T07:15', '2021-12-11T08:15', '2021-12-11T09:15', '2021-12-11T10:15']
# Get the timestamp value. A numeric value is needed for the underlying x-axis data
t_time_value = [datetime.fromisoformat(t_string).timestamp() for t_string in t_string_list]
# Get the x-axis ticks string values as HH:MM. Two ways
# ---- straight and unsafe way - It only works if the ISO Format will end with minutes! [...THH:MM]
t_ticks_values = [val[-5:] for val in t_string_list]
# --- Safe and general way: create a datetime object from isoformat and then convert to string
t_ticks_values = [datetime.fromisoformat(val).strftime('%H:%M') for val in t_string_list]
temp = [33.6, 31.6, 35.6, 32.6, 37.6]
# plot data: time, temp values
self.graphWidget.plot(t_time_value, temp)
# Get the x-axis
x_axis = self.graphWidget.getAxis('bottom')
# Check https://stackoverflow.com/questions/31775468/show-string-values-on-x-axis-in-pyqtgraph
ticks = [list(zip(t_time_value, t_ticks_values))]
x_axis.setTicks(ticks)
# Always start by initializing Qt (only once per application)
app = QApplication([])
window = MainWindow()
## Display the widget as a new window
window.show()
## Start the Qt event loop
app.exec_()
And here is the result:
For more advanced strategies, such as sub-classing AxisItem
for custom tickStrings
generator, please refer to this answer
Edit 1: Ticks downsamples
Note that you can downsample the ticks tuple in order to show less major/minor (in the example major only are present) ticks. As for instance, if you want to show one tick every 2 timestamps:
ticks = [list(zip(t_time_value, t_ticks_values))[::2]]
The result:
Answered By - Buzz
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.