Matplot Achsen umdrehen und Plott skalieren

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Benutzeravatar
mathman
User
Beiträge: 92
Registriert: Mittwoch 19. November 2008, 08:27
Wohnort: Magdeburg
Kontaktdaten:

Guten Abend,

ich erzeuge fürs Web z.Z. einen Plott,
wobei ich gerne den Plott skalieren (also ne Größe vorgeben) würde.

Außerdem möchte ich die y-Achse umdrehen, so dass alles negative oben ist.

Bis jetzt sieht mein Code wie folgt aus:

Code: Alles auswählen

...
#Axen reinigen von vorherigen Plot
  plt.cla()
  
  
  plt.plot(ecz[:,0] , min, label='Momenten Minimum', color='k', )
  plt.plot(ecz[:,0] , max, label='Momenten Maximum', color='k')
  plt.ylabel('Moment [kN/m]')
  plt.xlabel('Laenge [m]')
  plt.title('Momentenverlauf')
  plt.grid() # Gitternetz zeichnen
  plt.fill(ecz[:,0] , max, 'r') # Flaeche fuellen
  plt.fill(ecz[:,0] , min, 'b')

  #return plt.savefig(sys.stdout, format='png')
  plt.savefig(s, format='png')
  return s.getvalue()
Bild

Uploaded with ImageShack.us

Kann mir jemand sagen mit welchen Angaben ich das bewerkstellige? Aus der Doku habe ich leider nichts raus bekommen.

lg
Benutzeravatar
gkuhl
User
Beiträge: 600
Registriert: Dienstag 25. November 2008, 18:03
Wohnort: Hong Kong

Die Größe kannst du beim Erstellen der Figure (matplotlib.figure.Figure) festlegen. Nutze am besten die High-Level Funktion (matplotlib.pyplot.figure) dafür. Die Achse umzudrehen kannst du, indem du die Werte in "ylim" (z.B. "plt.ylim(10,-10)") vertauschst.

Grüße
Gerrit
Benutzeravatar
mathman
User
Beiträge: 92
Registriert: Mittwoch 19. November 2008, 08:27
Wohnort: Magdeburg
Kontaktdaten:

Vielen Dank,

funktioniert super :)
Benutzeravatar
mathman
User
Beiträge: 92
Registriert: Mittwoch 19. November 2008, 08:27
Wohnort: Magdeburg
Kontaktdaten:

Guten Abend,

leider funktioniert es doch nicht so wie ich es gedacht hatte :(

Wenn ich das Bild skaliert habe, dann fehlt ein Teil der Achsenbeschriftung links und unten im Plot. (siehe Bildschirmfoto). Ausserdem würde ich gerne die legende neben den Plot haben,
ist dies möglich ?

skalierte Bild
Bild

normale Größe
Bild

Ich erzeuge dabei die Plots mit folgendem Code

Code: Alles auswählen

def plot_schnittkraefte(string):
  
  import numpy, json, urllib, random
  import matplotlib.pyplot as plt
  #Lib fuer Ramdatei
  from StringIO import StringIO
  import sys
  
  #Json String auspacken  
  string = urllib.unquote(string)
  z = json.loads(string)
  typ = z["typ"]
  typ = int(typ)
  ecz = z["ecz"]
  ecz = numpy.array(ecz)
  
  #Momente der Lastfaelle zur Weiterverarbeitung aufbereiten filtern
  if typ == 1:
    #Momente der Lastfaelle in Container schreiben
    mlf = numpy.array([])
    for i in range(0,51,1):
      s = ecz[i,2:34:4] #Zeile,von Spalte:bis Spalte, Schritte
      mlf = numpy.append(mlf, s)
    mlf = numpy.reshape(mlf, (51,2))
  
  elif typ == 2:
    #Momente der Lastfaelle in Container schreiben
    mlf = numpy.array([])
    for i in range(0,102,1):
      s = ecz[i,2:34:4] #Zeile,von Spalte:bis Spalte, Schritte
      mlf = numpy.append(mlf, s)
    mlf = numpy.reshape(mlf, (102,4))
    
  else:
    #Momente der Lastfaelle in Container schreiben
    mlf = numpy.array([])
    for i in range(0,153,1):
      s = ecz[i,2:34:4] #Zeile,von Spalte:bis Spalte, Schritte
      mlf = numpy.append(mlf, s)
    mlf = numpy.reshape(mlf, (153,8))
    
  #Momenten Minimum bestimmen
  min = numpy.amin(mlf,1)
   
  #Momenten Maximum bestimmen
  max = numpy.amax(mlf,1)

  #Ausgabe als Plot
  #Plot  x,y
  s = StringIO()
  plt.figure(figsize=(8.0, 6.)) #breitexhoehe [px]
  #Axen reinigen von vorherigen Plot
  plt.cla()
  
  #Zeichen der Lastfaelle
  if typ == 1:
    plt.plot(ecz[:,0] , mlf[:,0], label= "LF 1", color = '#32cd32')
    plt.plot(ecz[:,0] , mlf[:,1], label= "LF 2", color = '#b8860b')
  elif typ == 2:
    plt.plot(ecz[:,0] , mlf[:,0], label= "LF 1", color = '#32cd32')
    plt.plot(ecz[:,0] , mlf[:,1], label= "LF 2", color = '#b8860b')
    plt.plot(ecz[:,0] , mlf[:,2], label= "LF 3", color = '#ff69b4')
    plt.plot(ecz[:,0] , mlf[:,3], label= "LF 4", color = '#48d1cc')
  else:
    plt.plot(ecz[:,0] , mlf[:,0], label= "LF 1", color = '#32cd32')
    plt.plot(ecz[:,0] , mlf[:,1], label= "LF 2", color = '#b8860b')
    plt.plot(ecz[:,0] , mlf[:,2], label= "LF 3", color = '#ff69b4')
    plt.plot(ecz[:,0] , mlf[:,3], label= "LF 4", color = '#48d1cc')
    plt.plot(ecz[:,0] , mlf[:,4], label= "LF 5", color = '#6a5acd')
    plt.plot(ecz[:,0] , mlf[:,5], label= "LF 6", color = '#ffd700')
    plt.plot(ecz[:,0] , mlf[:,6], label= "LF 7", color = '#8b0000')
    plt.plot(ecz[:,0] , mlf[:,7], label= "LF 8", color = '#bdb76b')

    
  plt.ylim(numpy.amax(max),numpy.amin(min)) # Negativ oben, Bereich einstellen
  plt.ylabel('Moment [kN/m]')
  plt.xlabel('Laenge [m]')
  plt.title('Momentenverlauf')
  plt.grid() # Gitternetz zeichnen
  plt.legend(ncol=(1), loc=(5))
  

  #return plt.savefig(sys.stdout, format='png')
  plt.savefig(s, format='png')
  return s.getvalue()
Des weiteren habe ich noch eine Funktion geschrieben, die den Plot füllen soll.
Dabei alles was in min drinne ist blau eingefärbt werden und alles was in max drinne ist blau eingefärbt werden. Als Einschränkung soll aber min nur bis < 0 rot eingefärbt werden und der Rest nicht, dass wollte ich mittels plt.fill(ecz[:,0] , min < 0 , 'b') realisieren, funktioniert aber leider nicht :K

Code: Alles auswählen

def plot_schnittkraefte_min_max(string):
  
  import numpy, json, urllib
  import matplotlib.pyplot as plt
  #Lib fuer Ramdatei
  from StringIO import StringIO
  import sys
  
  #Json String auspacken  
  string = urllib.unquote(string)
  z = json.loads(string)
  typ = z["typ"]
  typ = int(typ)
  ecz = z["ecz"]
  ecz = numpy.array(ecz)
  
  #Momente der Lastfaelle zur Weiterverarbeitung aufbereiten filtern
  if typ == 1:
    #Momente der Lastfaelle in Container schreiben
    mlf = numpy.array([])
    for i in range(0,51,1):
      s = ecz[i,2:34:4] #Zeile,von Spalte:bis Spalte, Schritte
      mlf = numpy.append(mlf, s)
    mlf = numpy.reshape(mlf, (51,2))
  
  elif typ == 2:
    #Momente der Lastfaelle in Container schreiben
    mlf = numpy.array([])
    for i in range(0,102,1):
      s = ecz[i,2:34:4] #Zeile,von Spalte:bis Spalte, Schritte
      mlf = numpy.append(mlf, s)
    mlf = numpy.reshape(mlf, (102,4))
    
  else:
    #Momente der Lastfaelle in Container schreiben
    mlf = numpy.array([])
    for i in range(0,153,1):
      s = ecz[i,2:34:4] #Zeile,von Spalte:bis Spalte, Schritte
      mlf = numpy.append(mlf, s)
    mlf = numpy.reshape(mlf, (153,8))

  
  #Momenten Minimum bestimmen
  min = numpy.amin(mlf,1)
  
   
  #Momenten Maximum bestimmen
  max = numpy.amax(mlf,1)

  #Ausgabe als Plot
  #Plot  x,y
  s = StringIO()
  plt.figure(figsize=(5.0, 3.8)) #breitexhoehe [px]
  #Axen reinigen von vorherigen Plot
  plt.cla()
  
  # Graphen plotten
  plt.plot(ecz[:,0] , min, label='Momenten Minimum', color='k', )
  plt.plot(ecz[:,0] , max, label='Momenten Maximum', color='k')
  plt.ylim(numpy.amax(max),numpy.amin(min)) # Negativ oben, Bereich einstellen
  #Achsen beschriften
  plt.ylabel('Moment [kN/m]')
  plt.xlabel('Laenge [m]')
  plt.title('Momentengrenzlinie')
  plt.grid() # Gitternetz zeichnen
  #Flaechen fuellen
  plt.fill(ecz[:,0] , max, 'r')
  plt.fill(ecz[:,0] , min < 0 , 'b')

  plt.savefig(s, format='png')
  return s.getvalue()
Bild

Hat jmd. eine Idee wie ich die Probleme lösen kann?
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo.

Ich würde erstmal meinen Code aufräumen ;-) In den Funktionen, welche quasi identisch sind, hast du selbst wieder nahezu identische Abschnitte.

Ach, ja: range(0,51,1) = range(51).

Sebastian
Das Leben ist wie ein Tennisball.
Benutzeravatar
mathman
User
Beiträge: 92
Registriert: Mittwoch 19. November 2008, 08:27
Wohnort: Magdeburg
Kontaktdaten:

So siehts doch schon besser aus ?! :)

Code: Alles auswählen

def mlf_filter(ecz, typ):
  import numpy
  #Momente der Lastfaelle zur Weiterverarbeitung aufbereiten filtern
  if typ == 1:
    #Momente der Lastfaelle in Container schreiben
    mlf = numpy.array([])
    for i in range(0,51,1):
      s = ecz[i,2:34:4] #Zeile,von Spalte:bis Spalte, Schritte
      mlf = numpy.append(mlf, s)
    mlf = numpy.reshape(mlf, (51,2))
  
  elif typ == 2:
    #Momente der Lastfaelle in Container schreiben
    mlf = numpy.array([])
    for i in range(0,102,1):
      s = ecz[i,2:34:4] #Zeile,von Spalte:bis Spalte, Schritte
      mlf = numpy.append(mlf, s)
    mlf = numpy.reshape(mlf, (102,4))
    
  else:
    #Momente der Lastfaelle in Container schreiben
    mlf = numpy.array([])
    for i in range(0,153,1):
      s = ecz[i,2:34:4] #Zeile,von Spalte:bis Spalte, Schritte
      mlf = numpy.append(mlf, s)
    mlf = numpy.reshape(mlf, (153,8))
  return mlf

def plot_schnittkraefte(string):
  
  import numpy, json, urllib, random
  import matplotlib.pyplot as plt
  #Lib fuer Ramdatei
  from StringIO import StringIO
  import sys
  
  #Json String auspacken  
  string = urllib.unquote(string)
  z = json.loads(string)
  typ = z["typ"]
  typ = int(typ)
  ecz = z["ecz"]
  ecz = numpy.array(ecz)
  
  #Momente der Lastfaelle zur Weiterverarbeitung aufbereiten filtern
  mlf = mlf_filter(ecz, typ)
    
  #Momenten Minimum bestimmen
  min = numpy.amin(mlf,1)
   
  #Momenten Maximum bestimmen
  max = numpy.amax(mlf,1)

  #Ausgabe als Plot
  #Plot  x,y
  s = StringIO()
  plt.figure(figsize=(8.0, 6.)) #breitexhoehe [px]
  #Axen reinigen von vorherigen Plot
  plt.cla()
  
  #Zeichnen der Lastfaelle
  if typ == 1:
    plt.plot(ecz[:,0] , mlf[:,0], label= "LF 1", color = '#32cd32')
    plt.plot(ecz[:,0] , mlf[:,1], label= "LF 2", color = '#b8860b')
  elif typ == 2:
    plt.plot(ecz[:,0] , mlf[:,0], label= "LF 1", color = '#32cd32')
    plt.plot(ecz[:,0] , mlf[:,1], label= "LF 2", color = '#b8860b')
    plt.plot(ecz[:,0] , mlf[:,2], label= "LF 3", color = '#ff69b4')
    plt.plot(ecz[:,0] , mlf[:,3], label= "LF 4", color = '#48d1cc')
  else:
    plt.plot(ecz[:,0] , mlf[:,0], label= "LF 1", color = '#32cd32')
    plt.plot(ecz[:,0] , mlf[:,1], label= "LF 2", color = '#b8860b')
    plt.plot(ecz[:,0] , mlf[:,2], label= "LF 3", color = '#ff69b4')
    plt.plot(ecz[:,0] , mlf[:,3], label= "LF 4", color = '#48d1cc')
    plt.plot(ecz[:,0] , mlf[:,4], label= "LF 5", color = '#6a5acd')
    plt.plot(ecz[:,0] , mlf[:,5], label= "LF 6", color = '#ffd700')
    plt.plot(ecz[:,0] , mlf[:,6], label= "LF 7", color = '#8b0000')
    plt.plot(ecz[:,0] , mlf[:,7], label= "LF 8", color = '#bdb76b')

    
  plt.ylim(numpy.amax(max),numpy.amin(min)) # Negativ oben, Bereich einstellen
  plt.ylabel('Moment [kN/m]')
  plt.xlabel('Laenge [m]')
  plt.title('Momentenverlauf')
  plt.grid() # Gitternetz zeichnen
  plt.legend(ncol=(1), loc=(5))
  

  #return plt.savefig(sys.stdout, format='png')
  plt.savefig(s, format='png')
  return s.getvalue()

def plot_schnittkraefte_min_max(string):
  
  import numpy, json, urllib
  import matplotlib.pyplot as plt
  #Lib fuer Ramdatei
  from StringIO import StringIO
  import sys
  
  #Json String auspacken  
  string = urllib.unquote(string)
  z = json.loads(string)
  typ = z["typ"]
  typ = int(typ)
  ecz = z["ecz"]
  ecz = numpy.array(ecz)
  
  #Momente der Lastfaelle zur Weiterverarbeitung aufbereiten filtern
  mlf = mlf_filter(ecz, typ)
  
  #Momenten Minimum bestimmen
  min = numpy.amin(mlf,1)
     
  #Momenten Maximum bestimmen
  max = numpy.amax(mlf,1)

  #Ausgabe als Plot
  #Plot  x,y
  s = StringIO()
  plt.figure(figsize=(5.0, 3.8)) #breitexhoehe [px]
  #Axen reinigen von vorherigen Plot
  plt.cla()
  
  # Graphen plotten
  plt.plot(ecz[:,0] , min, label='Momenten Minimum', color='k', )
  plt.plot(ecz[:,0] , max, label='Momenten Maximum', color='k')
  plt.ylim(numpy.amax(max),numpy.amin(min)) # Negativ oben, Bereich einstellen
  #Achsen beschriften
  plt.ylabel('Moment [kN/m]')
  plt.xlabel('Laenge [m]')
  plt.title('Momentengrenzlinie')
  plt.grid() # Gitternetz zeichnen
  #Flaechen fuellen
  plt.fill(ecz[:,0] , max, 'r')
  plt.fill(ecz[:,0] , min < 0 , 'b')

  plt.savefig(s, format='png')
  return s.getvalue()
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Eigentlich nicht. Da ist doch immer noch alles doppelt und dreifach vorhanden. Hier mal ein völlig ungetesteter Vorschlag mit schnell gewählten Namen. Du solltest übrigens an deiner Namensvergabe arbeiten, man versteht bei dem Code nichts.

Code: Alles auswählen

import numpy
import json
import urllib
import random
import matplotlib.pyplot as plt
from StringIO import StringIO
import sys

def mlf_filter(ecz, typ):
    size = 51 * typ

    #Momente der Lastfaelle in Container schreiben
    mlf = numpy.array([])
    for i in range(size):
      s = ecz[i,2:34:4] #Zeile,von Spalte:bis Spalte, Schritte
      mlf = numpy.append(mlf, s)
    
    returnnumpy.reshape(mlf, (size, 2**typ))


def unpack(string):
    string = urllib.unquote(string)
    z = json.loads(string)
    typ = int(z["typ"])
    ecz = numpy.array(z["ecz"])

    return typ, ecz

def even_more(string):
    typ, ecz = unpack(string)
    mlf = mlf_filter(ecz, typ)
    min, max = numpy.amin(mlf,1), numpy.amax(mlf,1)

    return typ, ecz, mlf, min, max


def spam(max, min):
    plt.ylim(numpy.amax(max),numpy.amin(min))
    plt.ylabel('Moment [kN/m]')
    plt.xlabel('Laenge [m]')
    plt.title('Momentenverlauf')
    plt.grid()


def init(w, h):
    plt.figure(figsize=(w, h.))
    plt.cla()

def eggs():
    s = StringIO()
    plt.savefig(s, format='png')
    return s.getvalue()


def plot_schnittkraefte(string):
    colors = ['#32cd32', ...]
    typ, ecz, mlf, min, max = even_more(string)

    init(8.0, 6.)

    for i, color in zip(range(2**typ), colors):
        plt.plot(ecz[:,0] , mlf[:,i], label= "LF %d" % i, color=color)

   
    spam(max, min)

    plt.legend(ncol=(1), loc=(5))

    return eggs()

def plot_schnittkraefte_min_max(string):
  typ, ecz, mlf, min, max = even_more(string)
  init(5.0, 3.8)
 
  # Graphen plotten
  plt.plot(ecz[:,0] , min, label='Momenten Minimum', color='k')
  plt.plot(ecz[:,0] , max, label='Momenten Maximum', color='k')

  spam(max, min)

  #Flaechen fuellen
  plt.fill(ecz[:,0] , max, 'r')
  plt.fill(ecz[:,0] , min < 0 , 'b')

  return eggs()
Da kann man immer noch viel verbessern, aber dazu habe ich gerade keine Lust.
Das Leben ist wie ein Tennisball.
Benutzeravatar
gkuhl
User
Beiträge: 600
Registriert: Dienstag 25. November 2008, 18:03
Wohnort: Hong Kong

@mathman: Zur extrem schlechten Qualität habe ich an anderen Stellen schon genug geschrieben. Da du leider ziemlich lernresistent bist, belasse ich es mal dabei.
Wenn ich das Bild skaliert habe, dann fehlt ein Teil der Achsenbeschriftung links und unten im Plot. (siehe Bildschirmfoto). Ausserdem würde ich gerne die legende neben den Plot haben,
ist dies möglich ?
Ja, siehe Dokumentation von Matplotlib.
[...] min drinne ist blau [...], dass wollte ich mittels plt.fill(ecz[:,0] , min < 0 , 'b') realisieren, funktioniert aber leider nicht
Bei mir ist der Ausdruck "min < 0" "False".

Grüße
Gerrit
Benutzeravatar
mathman
User
Beiträge: 92
Registriert: Mittwoch 19. November 2008, 08:27
Wohnort: Magdeburg
Kontaktdaten:

@EyDu

vielen Dank für das Beispiel.

Kann ich denn überhaupt bei einer Funktion mehrere Rückgabewerte zurück geben ?

Code: Alles auswählen

def unpack(string):
    string = urllib.unquote(string)
    z = json.loads(string)
    typ = int(z["typ"])
    ecz = numpy.array(z["ecz"])

    return typ, ecz
Ich habe das einmal probiert, jedoch kommt dann die Fehlermeldung das ecz und typ global nicht verfügbar wären :K

@gkuhl
danke, ich versuche jede konstruktive Kritik aufzunehmen und mich zu verbessern.
Wird sicherlich noch lange dauern bis ich schönen Code schreibe :|

"min < 0", das funktioniert bei mir leider auch nicht. in der Doku habe ich nun die Funktion "fill_between" gefunden was theoretisch das Problem löst. Leider funktioniert der Ansatz aber nicht immer und so muss ich in dem Array max irgendwie alle Werte <0 zu 0 setzen und bei min alle Werte >0 zu 0 setzen.
Benutzeravatar
mkesper
User
Beiträge: 919
Registriert: Montag 20. November 2006, 15:48
Wohnort: formerly known as mkallas
Kontaktdaten:

mathman hat geschrieben: Kann ich denn überhaupt bei einer Funktion mehrere Rückgabewerte zurück geben ?
JA.
mathman hat geschrieben:Ich habe das einmal probiert, jedoch kommt dann die Fehlermeldung das ecz und typ global nicht verfügbar wären :K
Evtl. stimmte die Einrückung nicht?

Code: Alles auswählen

def spam():
     b = 2
     a = 1
     return a,b
 
>>> spam()
(1, 2)
Benutzeravatar
mathman
User
Beiträge: 92
Registriert: Mittwoch 19. November 2008, 08:27
Wohnort: Magdeburg
Kontaktdaten:

@mkesper

ich hab leider nicht gewusst das ein Tupel zurück geliefert wird :oops:

leider habe ich noch gar keine Ahnung wie man den kompletten Plot skaliert :cry:

*nachtrag*

habs doch geschafft ...

Code: Alles auswählen

from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
from matplotlib.figure import Figure

  fig = Figure()
  canvas = FigureCanvas(fig)
  fig = Figure(figsize=(7,5))
  canvas = FigureCanvas(fig)
  ax = fig.add_axes([0.15,0.15,0.6,0.75]) # X-Plotausgabe,Y-Plotausgabe,Breite,Hoehe [%]
  ax.set_xlabel('Laenge [m]', size='x-small')
  ax.set_ylabel('Moment [kN/m]', size='x-small')
  ax.set_title('Momentengrenzlinie', size='x-small')
  ax.plot(ecz[:,0] , min, label='M max', color='k')
  ax.fill_between(ecz[:,0] , 0 , min, color = 'b')
  ax.plot(ecz[:,0] , max, label='M Min', color='k')
  ax.fill_between(ecz[:,0] , max, 0 , color = 'r')
  ax.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0., prop={"size":10})
  ax.set_ylim(numpy.amax(max),numpy.amin(min)) # Negativ oben, Bereich einstellen
  ax.set_xlim(0,numpy.amax(ecz[:,0])) # Negativ oben, Bereich einstellen
  

  canvas.print_figure(s, format='png')
  return s.getvalue()
Jedoch habe ich keine Ahnung wie man die Schrift von der X und Y-Achse klein bekommt und bei min und max die Anteile zu 0 setzt :K

Bild
Antworten