Finde den Fehler?! Graphen spinnen

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Robbse1990
User
Beiträge: 16
Registriert: Montag 16. Oktober 2017, 10:29

Finde den Fehler?! Graphen spinnen

Beitragvon Robbse1990 » Sonntag 12. November 2017, 15:22

Hallo Zusammen,

Ich arbeite mit jupyter notebook, ipython, matplotlib

folgendes Vorgehen:

Datei auslesen, Daten verarbeiten, Graph erstellen, Graph abspeichern als pdf

Dabei tritt folgendes Problem auf:

Wenn ich mir den Graphen mit plt.show anzeigen lasse, kann ich im Code beliebig viel ändern, und der Graph passt sich an. Nach einer undefinierbaren Anzahl von Änderungen, fängt der Graph an zu "spinnen". Plotten alle Daten auf 3 X-werte, oder er nimmt random daten dazu usw. Kein Plan warum das passiert und warum so random. Ein Neustart des PC's löst das Problem.
Wenn ich nun die Datei noch zusätzlich abspeicher, passt der erste graph, der 2. nach einer Änderung im Code schon überhaupt nicht mehr. Auch wenn ich die pdf Datei vor dem erneuten speichern lösche, kommt es zum selben Problem.

Jetzt zu meiner Frage:

Hat jemand eine Ahnung wo das Problem liegen könnte, anscheinend kommt mein PC/Programm ja mit dem Speicher durcheinander. Hat jemand Ähnliche Erfahrungen mit so was? Hat matplotlib Probleme beim wiederholen vom Erstellen von Graphen, oder eher jupyter oder ist es ungeeignet das ganze als pdf abzuspeichern? Oder, könnte es am Code liegen? Gerne posten ich den, falls jemand das sehen will.

Danke für jeden Tip im Voraus!

Gruß Robin
Sirius3
User
Beiträge: 7052
Registriert: Sonntag 21. Oktober 2012, 17:20

Re: Finde den Fehler?! Graphen spinnen

Beitragvon Sirius3 » Sonntag 12. November 2017, 15:49

@Robbse1990: was passiert denn, wenn Du ohne Jupyter arbeitest? Was Du da genau machst, verstehe ich nicht, vielleicht hilft ja der Code beim Verstehen.
narpfel
User
Beiträge: 146
Registriert: Freitag 20. Oktober 2017, 16:10

Re: Finde den Fehler?! Graphen spinnen

Beitragvon narpfel » Sonntag 12. November 2017, 15:54

Moin,

ich hab’ dieses Verhalten noch nicht gesehen (aber ich benutze quasi immer das `inline`-Backend im Jupyter Notebook). Zur Fehlersuche (und insbesondere, wenn du Code zeigst): Versuche, ein Minimalbeispiel zu finden, das den Fehler zeigt. Also sukzessive Teile des Codes entfernen und gucken, ob der Fehler immer noch auftritt. Dabei findet man den Fehler sehr oft selbst, und wenn nicht, dann ist es für andere viel leichter zu helfen.

Ein Neustart des PC's löst das Problem.

Was passiert, wenn du den Kernel des Notebooks neustartest?

Tritt der Fehler auch mit einem anderen `matplotlib`-Backend auf?
Robbse1990
User
Beiträge: 16
Registriert: Montag 16. Oktober 2017, 10:29

Re: Finde den Fehler?! Graphen spinnen

Beitragvon Robbse1990 » Sonntag 12. November 2017, 16:44

Ich hab den Code nun auf einem anderen PC und ohne ipyhton getestet, selbes Problem. Aber ich weiß jetzt wo das eine Problem liegt:

def funk_1(a,b,c):
return a+b+c
def funk_2(a,b,c):
return 2*a+3*b+c

funk1_(1,2,3)
funk_2(1,2,3)

----> Bullshit

Wenn ich die Funktionen nicht beide aufrufe, passt es. Muss ich hier mit globalen Variablen arbeiten oder was anderem? ICh hätte gerne in einem Programm zwei, oder mehr Funktionen, die Verschiedenes mit den gleichen Parametern machen, aber sich nicht gegenseitig beeinflussen, was mach ich da?

Konkret geht es darum:
Ich habe eine Liste, in jeder Zeile steht Datum, Temperatur, Luftfeuchtigkeit, je mit tab getrennt. Jede halbe Stunde kommt eine Zeile dazu
Nun möchte ich diese Daten plotten. Einmal die letzten 30 tage mit je dem Tagesdurchschnitt von T und H, und, falls die Werte Grenzen überschreiten, ein Graph mit den letzten 300 (oder sonst eine Zahl) Einträgen. Die beiden graphen einzeln bekomme ich hin, nur hätte ich das gerne ungefähr so in einem Programm:

def funk_30_tage(datei_pfad,wie_viele_daten):

def funk_letzten_x_eintraege(datei_pfad):

Wie mach ich das, das sich die variablen und Listen nicht in die Quere kommen?


Das andere Problem, mit den random Fehlern, kann auch mit Neustart von Jupyter gelöst werden, wahrscheinlich liegt es daran.
Sirius3
User
Beiträge: 7052
Registriert: Sonntag 21. Oktober 2012, 17:20

Re: Finde den Fehler?! Graphen spinnen

Beitragvon Sirius3 » Sonntag 12. November 2017, 16:54

@Robbse1990: so wie Du Deine Funktionen hier zeigst, könne sie sich nicht in die Quere kommen. Du mußt den wirklichen Code posten, damit man sehen kann, was Du falsch machst.
narpfel
User
Beiträge: 146
Registriert: Freitag 20. Oktober 2017, 16:10

Re: Finde den Fehler?! Graphen spinnen

Beitragvon narpfel » Sonntag 12. November 2017, 16:57

Eventuell ist auch `pandas` einen Blick wert.
Robbse1990
User
Beiträge: 16
Registriert: Montag 16. Oktober 2017, 10:29

Re: Finde den Fehler?! Graphen spinnen

Beitragvon Robbse1990 » Sonntag 12. November 2017, 17:03

hier mal der code. das ganze soll auf dem raspi laufen. wenn ein monat rum ist, soll ich ein mail bekommen mit dem monatsreport. und falls die Werte die Grenzen überschreiten, soll ich eine "alarm"Mail bekommen mit dem zugehörigen Graph. Damit will ich meinen Keller vor Feuchtigkeit schützen.
  1. ##############################################
  2. ###plot fuer monatsreprot und Alarm Graphen###
  3. ##############################################
  4.  
  5. import matplotlib.pyplot as plt
  6. from copy import deepcopy
  7.  
  8.  
  9.  
  10. def graph_schnitt(grenzwert, laenge_uebergabe_liste, datei_pfad):  
  11.    
  12.     #############################################################################################################
  13.     #Datei einlesen und fuer jeden tag den durschnitt berechnen
  14.  
  15.     temp_list = []
  16.     temp_list_berech = []
  17.     hum_list  = []
  18.     hum_list_berech = []
  19.     date_list = []
  20.  
  21.     with open(datei_pfad, 'rb') as fh: #ersten tag definieren
  22.         for line in fh:  
  23.             tag = line[0:3]
  24.             date_list.append(line[0:14])
  25.             break
  26.     with open(datei_pfad, 'rb') as fh: #tag einlesen und in liste schreiben um spaeter durchschnitt zu berechnen
  27.         for line in fh:
  28.             if line[0:3] == tag:
  29.                 temp_list_berech.append(float(line[24:28]))  
  30.                 hum_list_berech.append(float(line[29:34]))  
  31.             else:
  32.                 tag = line[0:3]  
  33.                 temp_list.append(sum(temp_list_berech)/len(temp_list_berech))
  34.                 temp_list_berech = []
  35.                 temp_list_berech.append(float(line[24:28]))
  36.                 hum_list.append(sum(hum_list_berech)/len(hum_list_berech))
  37.                 hum_list_berech = []
  38.                 hum_list_berech.append(float(line[29:34]))
  39.                 date_list.append(line[0:14])
  40.     temp_list.append(sum(temp_list_berech)/len(temp_list_berech))
  41.     hum_list.append(sum(hum_list_berech)/len(hum_list_berech))            
  42.    
  43.    
  44.     ############################################################################################################
  45.     #Sichergehen, damit lange der liste ausreicht
  46.    
  47.     if len(temp_list) < laenge_uebergabe_liste:
  48.         laenge_uebergabe_liste = len(temp_list)
  49.    
  50.  
  51.     ############################################################################################################
  52.     #Welche Werte werden aus der liste genommen und listen sicher kopieren
  53.  
  54.     temp_list_plot = deepcopy(temp_list[-laenge_uebergabe_liste:])
  55.     hum_list_plot = deepcopy(hum_list[-laenge_uebergabe_liste:])
  56.     date_list_plot = [""]*len(date_list) #leere Liste die spaeter mit date gefuellt wird
  57.  
  58.     ############################################################################################################
  59.     #bestimmen, wie viele werte auf x achse angezeigt werden
  60.  
  61.     if laenge_uebergabe_liste <= 10:
  62.         date_list_plot = date_list
  63.     elif 10 < laenge_uebergabe_liste <= 20:
  64.         for i in range(1,len(date_list),2): #loeschen von jedem zweiten ,bzw. in leer machen
  65.             date_list_plot[i] = date_list[i]
  66.     elif 20 < laenge_uebergabe_liste <= 50:   #und bei sehr vielen daten halt ueberall "0"
  67.         for i in range(1,len(date_list),5):
  68.             date_list_plot[i]=date_list[i]
  69.     elif laenge_uebergabe_liste > 50:
  70.         pass
  71.  
  72.  
  73.     ############################################################################################################
  74.     #Durschnitt bestimmen und max Werte
  75.  
  76.     temp_durchschnitt = sum(temp_list_plot)/len(temp_list_plot)
  77.     temp_durchschnitt_plot = [temp_durchschnitt]*laenge_uebergabe_liste
  78.  
  79.     hum_durchschnitt = sum(hum_list_plot)/len(hum_list_plot)
  80.     hum_durchschnitt_plot = [hum_durchschnitt]*laenge_uebergabe_liste
  81.  
  82.     richtlinie_werte = [grenzwert]*laenge_uebergabe_liste #liste mit werten fuer die grenzlinie bei grenzwert
  83.  
  84.     ##############################################################################################################
  85.     #der Plot selbst
  86.  
  87.     range_list = range(1,laenge_uebergabe_liste+1)
  88.  
  89.     ax1 = plt.subplot()
  90.     ax1.plot(range_list,temp_list_plot,'r')
  91.     ax1.plot(range_list,temp_durchschnitt_plot,'r_')
  92.     ax1.set_ylabel("Temperatur [$^\circ$C]",color='r')
  93.     ax1.tick_params('y', direction='inout', color='r', labelcolor='r')
  94.     ax1.set_ylim((min(temp_list_plot)-0.75),max(temp_list_plot)+0.75) #Lage der Fkten bestimmen
  95.  
  96.  
  97.     ax1.text(1, temp_durchschnitt+temp_durchschnitt*0.001, '$T_D = {0:s}^\circ C$'.format(str(temp_durchschnitt)[:4]), color='r', fontsize=10)
  98.  
  99.  
  100.     ax2 = ax1.twinx()
  101.     ax2.set_ylabel("rel. Luftfeuchtigkeit [%]", color='b')
  102.     ax2.tick_params('y', direction='inout', color='b', labelcolor='b')
  103.     ax2.plot(range_list,hum_list_plot,'b')
  104.     ax2.plot(range_list,hum_durchschnitt_plot,'b_')
  105.     ax2.plot(range_list,richtlinie_werte, '-.',linewidth=1.0, color='dodgerblue')
  106.     ax2.set_ylim(min(hum_list_plot)-1.5)
  107.     ax2.text(1, hum_durchschnitt+0.1, '$H_D = {0:s}$%'.format(str(hum_durchschnitt)[:4]), color='b', fontsize=10)
  108.     ax1.set_xticks(range_list)
  109.     ax1.set_xticklabels(date_list_plot[-laenge_uebergabe_liste:], rotation='45', fontsize=9, ha='right')
  110.  
  111.  
  112.     ##############################################################################################################
  113.     #Title und Datei speichern
  114.  
  115.  
  116.     plt.title("Messdaten vom " + date_list[-laenge_uebergabe_liste][0:20] + " bis " + date_list[-1][0:20])  
  117.     save_name = 'Messdaten_vom_{0:s}.pdf'.format(date_list[-laenge_uebergabe_liste][4:20]) #das mag kein : im Namen
  118.     plt.savefig(save_name, bbox_inches='tight', format='pdf')
  119.     #plt.show()
  120.  
  121.  
  122.     ##############################################################################################################
  123.     #funktion gibt save name aus
  124.  
  125.     return save_name
  126.  
  127.  
  128. ###################################################################################################################
  129. ###################################################################################################################
  130. ###################################################################################################################
  131. ###################################################################################################################
  132. ###################################################################################################################
  133. ###################################################################################################################
  134.  
  135.  
  136. def graph_alarm(grenzwert, datei_pfad):
  137.    
  138.     #############################################################################################################
  139.     #Datei einlesen und letzten 7 Tage anzeigen, alle werte
  140.  
  141.     laenge_uebergabe_liste =350  
  142.      
  143.     temp_list = []
  144.     hum_list  = []
  145.     date_list = []
  146.  
  147.     with open(datei_pfad, 'rb') as fh: #tag einlesen und in liste schreiben um spaeter durchschnitt zu berechnen
  148.         for line in fh:
  149.             date_list.append(line[0:20])
  150.             temp_list.append(float(line[24:28]))  
  151.             hum_list.append(float(line[29:34]))
  152.  
  153.     ############################################################################################################
  154.     #Welche Werte werden aus der liste genommen und listen sicher kopieren
  155.  
  156.     temp_list_plot = deepcopy(temp_list[-laenge_uebergabe_liste:])
  157.     hum_list_plot  = deepcopy(hum_list[-laenge_uebergabe_liste:])
  158.     date_list_plot = [""]*len(date_list)
  159.  
  160.     richtlinie_werte = [grenzwert]*laenge_uebergabe_liste #liste mit werten fuer die grenzlinie bei grenzwert
  161.  
  162.     ##############################################################################################################
  163.     #der Plot selbst
  164.  
  165.     range_list = range(1,laenge_uebergabe_liste+1)
  166.  
  167.     ax1 = plt.subplot()
  168.     ax1.plot(range_list,temp_list_plot,'r')
  169.     ax1.set_ylabel("Temperatur [$^\circ$C]",color='r')
  170.     ax1.tick_params('y', direction='inout', color='r', labelcolor='r')
  171.     ax1.set_ylim((min(temp_list_plot)-0.75),max(temp_list_plot)+0.75) #Lage der Fkten bestimmen
  172.  
  173.  
  174.     ax2 = ax1.twinx()
  175.     ax2.set_ylabel("rel. Luftfeuchtigkeit [%]", color='b')
  176.     ax2.tick_params('y', direction='inout', color='b', labelcolor='b')
  177.     ax2.plot(range_list,hum_list_plot,'b')
  178.     ax2.plot(range_list,richtlinie_werte, '-.',linewidth=1.0, color='dodgerblue')
  179.     ax2.set_ylim(min(hum_list_plot)-1.5)
  180.     ax1.set_xticks(range_list)
  181.     ax1.set_xticklabels(date_list_plot[-laenge_uebergabe_liste:], rotation='45', fontsize=9, ha='right')
  182.     ax1.set_xlabel("Letzten {0:s} Messwerte (ca. 1 Woche), zwei pro Stunde".format(str(laenge_uebergabe_liste)))
  183.     ax1.set_xticks([])
  184.  
  185.     plt.title("Messdaten vom " + date_list[-laenge_uebergabe_liste][0:20] + " bis " + date_list[-1][0:20])  
  186.     save_name = 'Alarm_vom_{0:s}.pdf'.format(date_list[-1][4:14]) #das mag kein : im Namen
  187.     plt.savefig(save_name, bbox_inches='tight', format='pdf')
  188.     #print save_name
  189.     #plt.show()
  190.  
  191.     return save_name
  192.  
  193.  
  194.    
  195.    





  1. grenzwert = 65.0
  2. laenge_uebergabe_liste =30    
  3. datei_pfad = 'Messdaten.txt'
  4.  
  5. aaa = graph_schnitt(grenzwert, laenge_uebergabe_liste, datei_pfad)
  6. print (aaa)
  7. bbb = graph_alarm(grenzwert,datei_pfad)
  8. print (bbb)
  9.  
  10.  
  11.  
narpfel
User
Beiträge: 146
Registriert: Freitag 20. Oktober 2017, 16:10

Re: Finde den Fehler?! Graphen spinnen

Beitragvon narpfel » Sonntag 12. November 2017, 17:12

Das ist genau das, was ich mit einem Minimalbeispiel nicht meinte. :wink:

Nachdem du den Code gezeigt hast: Du möchtest definitiv `pandas` benutzen. Und den Code sinnvoll strukturieren, also auf Funktionen aufteilen, die jeweils eine Aufgabe haben. Also: Eine, die die Daten liest, eine pro Berechnung/Auswertung und eine für den Plot.

Zum Problem: Hast du mal versucht, `plt.close()` nach dem `plt.savefig` einzufügen?
Robbse1990
User
Beiträge: 16
Registriert: Montag 16. Oktober 2017, 10:29

Re: Finde den Fehler?! Graphen spinnen

Beitragvon Robbse1990 » Sonntag 12. November 2017, 17:27

ok, ich werde mir mal pandas anschauen. UND, plt.close() scheint das Problem gelöst zu haben - Danke!
narpfel
User
Beiträge: 146
Registriert: Freitag 20. Oktober 2017, 16:10

Re: Finde den Fehler?! Graphen spinnen

Beitragvon narpfel » Sonntag 12. November 2017, 18:02

Zur Erklärung: `matplotlib.pyplot` hat ein globales `Figure`-Objekt, das mit den Funktionen aus `pyplot` manipuliert wird. Wenn man zwischen zwei separaten Graphen nicht `plt.close` aufruft, plottet man mit dem selben `Firgure`-Objekt, und das führt meist zu Mist.

Wer ist online?

Mitglieder in diesem Forum: Yahoo [Bot]