Seite 1 von 1
UnixTime in Animate Funktion
Verfasst: Donnerstag 27. Juli 2017, 10:22
von Mauby
Hallo an alle,
Ich sitze gerade an einem Projekt einen Beschleunigungssensor per I2C mit einem Raspberry auszulesen und live auf einem Graph mit Python und Matplotlib anzuzeigen.
Ich scheitere aber aktuell an der Zeitanzeige für den Graphen.
Meine Datendatei hat das Format wie 1501019372.741470;+240 als unix time mit µsec und als Daten die Beschleunigung
Ich wollte folgenden Code benutzen:
https://www.youtube.com/watch?v=ZmYPzES ... a1fPDKluPF
Und dazu die Umwandlung von Unix Time:
https://www.youtube.com/watch?v=aRQxMYo ... F&index=11
Funktioniert aber nicht so wirklich...
Meine aktuelle animate Funktion sieht so aus:
Code: Alles auswählen
def animate(i):
graph_data=open('/home/pi/pi_test/beschleunigung.txt','r').read()
lines = graph_data.split('\n')
xs=[]
ys=[]
for line in lines:
if len(line)>1:
x.y = line.split(';')
dateconv = np.vectorize(dt.datetime.fromtimestamp)
x=dateconv(x)
xs.append(x)
ys.append(y)
ax1.clear()
ax1.plot(xs,ys)
Bin neu in Python und Raspberry, deswegen stehe ich gerade bisschen auf dem Schlauch bei den Fehlern, die er mir ausspuckt.
Grüße.
Mauby
Re: UnixTime in Animate Funktion
Verfasst: Donnerstag 27. Juli 2017, 10:52
von BlackJack
Mauby: Funktioniert aber nicht so wirklich ist keine so wirklich gute Fehlerbeschreibung. Was erwartest Du denn, und warum, und was passiert denn stattdessen? Oder bekommst Du vielleicht eine Fehlermeldung? Wenn ja welche? Und wo? Dazu wäre der Traceback interessant.
Bei dem gezeigten Quelltext fehlt die Einrückung, die ist in Python wichtig. Falls dort Fehler liegen müssten wir jetzt raten wie die denn bei Dir tatsächlich aussieht.
Sonstige Anmerkungen:
Dateien die man öffnet sollte man auch wieder schliessen. In dem Zusammenhang ist die ``with``-Anweisung ganz nützlich.
`dateconv` macht hier nicht wirklich sinn, denn `x` ist ein Skalar.
Re: UnixTime in Animate Funktion
Verfasst: Donnerstag 27. Juli 2017, 11:05
von Mauby
Ok, ich logge mich gerade über den raspberry ins internet ein, jetzt kann ich den code komplett kopieren:
Code: Alles auswählen
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
import matplotlib.dates as mdates
import datetime as dt
#import time
from matplotlib import style
style.use('dark_background')
#print(plt.style.available)
##def bytespdate2num(fmt, encoding='utf-8'):
## strconverter = mdates.strpdate2num(fmt)
## def bytesconverter(b):
## s = b.decode(encoding)
## return strconverter(s)
## return bytesconverter
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)
def animate(i):
graph_data = open('/home/pi/pi_beschleunigung_daten','r').read()
lines = graph_data.split('\n')
xs = []
ys = []
for line in lines:
if len(line)>1:
x, y = line.split(';')
xs.append(x)
ys.append(y)
dateconv = np.vectorize(dt.datetime.fromtimestamp)
xs = dateconv(xs)
ax1.clear()
ax1.plot(xs, ys)
ani = animation.FuncAnimation(fig, animate, interval=250)
plt.xlabel('Time')
plt.ylabel('Accelleration')
plt.show()
Fehlercode kommt und zeigt an:
Code: Alles auswählen
Traceback (most recent call last):
File "/home/pi/pi_beschleunigung.py", line 41, in <module>
ani = animation.FuncAnimation(fig, animate, interval=250)
File "/usr/lib/python3/dist-packages/matplotlib/animation.py", line 1052, in __init__
TimedAnimation.__init__(self, fig, **kwargs)
File "/usr/lib/python3/dist-packages/matplotlib/animation.py", line 898, in __init__
*args, **kwargs)
File "/usr/lib/python3/dist-packages/matplotlib/animation.py", line 576, in __init__
self._init_draw()
File "/usr/lib/python3/dist-packages/matplotlib/animation.py", line 1077, in _init_draw
self._draw_frame(next(self.new_frame_seq()))
File "/usr/lib/python3/dist-packages/matplotlib/animation.py", line 1091, in _draw_frame
self._drawn_artists = self._func(framedata, *self._args)
File "/home/pi/pi_beschleunigung.py", line 35, in animate
xs = dateconv(xs)
File "/usr/lib/python3/dist-packages/numpy/lib/function_base.py", line 1573, in __call__
return self._vectorize_call(func=func, args=vargs)
File "/usr/lib/python3/dist-packages/numpy/lib/function_base.py", line 1633, in _vectorize_call
ufunc, otypes = self._get_ufunc_and_otypes(func=func, args=args)
File "/usr/lib/python3/dist-packages/numpy/lib/function_base.py", line 1597, in _get_ufunc_and_otypes
outputs = func(*inputs)
TypeError: an integer is required (got type numpy.str_)
Re: UnixTime in Animate Funktion
Verfasst: Donnerstag 27. Juli 2017, 11:21
von BlackJack
@Mauby: `x` und `y` sind Zeichenketten. `datetime.fromtimestamp()` und damit auch `dateconv()` erwarten aber Zahlen. Bei `ys` würde es beim Plotten dann später das gleiche Problem geben.
Da Du sowieso schon `numpy` verwendest, würde ich gleich dessen Funktionen zum Einlesen von CSV/Textdateien verwenden statt das selbst auszuprogrammieren.
Schau Dir mal `numpy.loadtxt()` an. Das `unpack`-Argument wäre hier auch nützlich.
Re: UnixTime in Animate Funktion
Verfasst: Donnerstag 27. Juli 2017, 14:31
von Mauby
Hab es jetzt soweit hinbekommen mit numpy... Folgend ist der Code
Code: Alles auswählen
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
import matplotlib.dates as mdates
import datetime as dt
#import time
from matplotlib import style
style.use('dark_background')
#print(plt.style.available)
##def bytespdate2num(fmt, encoding='utf-8'):
## strconverter = mdates.strpdate2num(fmt)
## def bytesconverter(b):
## s = b.decode(encoding)
## return strconverter(s)
## return bytesconverter
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)
def animate(i):
graph_data = '/home/pi/pi_audi/audi_beschleunigung_daten'
x, y = np.loadtxt(graph_data,
delimiter=';',
unpack=True)
dateconv = np.vectorize(dt.datetime.fromtimestamp)
x = dateconv(x)
ax1.clear()
for label in ax1.xaxis.get_ticklabels():
label.set_rotation(45)
ax1.tick_params(axis='x', width='1')
ax1.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M:%S'))
ax1.grid(True)
ax1.plot(x, y)
plt.subplots_adjust(bottom=0.18)
plt.xlabel('Time')
plt.ylabel('Accelleration')
ani = animation.FuncAnimation(fig, animate, interval=250)
plt.show()
## Zusätzlicher Code zum Merken:
##
## dateconv = np.vectorize(dt.datetime.fromtimestamp)
## xs = dateconv(xs)
Re: UnixTime in Animate Funktion
Verfasst: Freitag 28. Juli 2017, 07:58
von Mauby
Guten Morgen Allerseits
Hätte noch eine Frage dazu:
Aktuell schreibt mein C Programm vom Beschleunigungssensor alles in eine Datei untereinander. Irgendwann muss dann Python ne meeenge Daten plotten und ich sehe in meinem Graphen nichts mehr.
Daher würde ich gerne die x-Achsen skalierung verkleinern, so dass der Graph nur die letzten ca 1000 Datenpunkte anzeigt.
Kann man das mit nump.loadtxt() machen mit der Funktion
skiprows : int, optional
Skip the first skiprows lines; default: 0
In Kombination mit der Länge / Anzahl der Reihen in der Datei. Zb sowas wie :
Code: Alles auswählen
if length of Datei > 1000
skiprows=length-1000
else
skiprows=0
Oder gibt es dafür elegantere Methoden?
Grüße,
Mauby
Re: UnixTime in Animate Funktion
Verfasst: Freitag 28. Juli 2017, 08:09
von BlackJack
@Mauby: Um zu wissen wie viele Zeilen eine Textdatei hat muss man sie lesen. Das heisst Du musst die sowieso einlesen. Und danach kannst Du Dir einfach per „slicing“ die letzten 1000 davon nehmen.
Falls die Datei dazu zu gross wird sie komplett in den Speicher zu laden, sollte man überlegen ob eine einfach Textdatei dafür geeignet ist. Man könnte über das regelmässige wechseln der Datei nachdenken, beispielsweise eine pro Tag oder Stunde oder … je nach dem wie hoch das Datenaufkommen ist. Oder man verwendet eine Datenbank. Eine SQL-Datenbank (SQLite, MySQL/MariaDB, PostgreSQL, …) oder vielleicht auch etwas spezielleres wie HDF5.
Re: UnixTime in Animate Funktion
Verfasst: Freitag 28. Juli 2017, 08:31
von Mauby
Slicing... Ok
Also würde sowas klappen:
Code: Alles auswählen
date = numpy.loadtxt(...)
date_s = date[len(date)-1000:]
soweit würde ich das verstehen von
http://pythoncentral.io/cutting-and-sli ... in-python/
probiere ich gleich mal aus...
Re: UnixTime in Animate Funktion
Verfasst: Freitag 28. Juli 2017, 08:43
von snafu
Den ersten Teil beim Slicing-Ausdruck kannst du weglassen, denn date[len(date)-1000:] lässt sich auch kürzer als date[-1000:] ausdrücken. Das hat beides exakt den gleichen Effekt.