Matplotlib und Bottel

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.
Benutzeravatar
mathman
User
Beiträge: 92
Registriert: Mittwoch 19. November 2008, 08:27
Wohnort: Magdeburg
Kontaktdaten:

Leonidas hat geschrieben:
mathman hat geschrieben:Wenn das Bild ausgegeben wurde, bleibt das dann im Arbeitsspeicher oder wird das dann automatisch gelöscht? Weil wenn das Programm auf einem Server ständig läuft, wäre ja irgendwann der Arbeitsspeicher voll :lol:
Das Objekt bleibt so lange im Speicher wie lange es noch Referenzen drauf gibt. Wie jedes Objekt in Python eben :roll:
Ok :D

Jetzt wäre nur noch das Problem wie ich das Bild und html Code an den Nutzer schicken könnte ...
frabron
User
Beiträge: 306
Registriert: Dienstag 31. März 2009, 14:36

Na, eine Route für's HTML, und eine für das Bild. Im Template der HTML-Route verweist du im Bild-Element (das <img - Ding ;) ) für dein Bild auf die Bild-Route und fertig.
Benutzeravatar
mathman
User
Beiträge: 92
Registriert: Mittwoch 19. November 2008, 08:27
Wohnort: Magdeburg
Kontaktdaten:

frabron hat geschrieben:Na, eine Route für's HTML, und eine für das Bild. Im Template der HTML-Route verweist du im Bild-Element (das <img - Ding ;) ) für dein Bild auf die Bild-Route und fertig.
Ok das funktioniert soweit :mrgreen:

Code: Alles auswählen

from bottle import route, run, static_file, debug, response
@route('/')
@route('/index.html')
def index():
    
    return """
    <p><img src="bild.png" alt="Plot"></p>
    """
@route('/bild.png')
def plot_schnittkraefte():
    from schnitt_test import schnittkraefte
    s = schnittkraefte(3, 2.25, 26700000., 5, 10, 30, 10, 20, 20, 20)
    from plot import plot_schnittkraefte
    s = plot_schnittkraefte(s)
    response.headers['Content-Type'] = 'image/png'
    return s
  
debug(True)
run(host='localhost', port=8080)
Jetzt besteht das Problem darin, dass ich z.B. die Daten aus der Funktion "schnittkraefte" zum plotten und für die Ausgabe auf der HTML Seite brauche.

Dafür reicht es ja die Werte einmal berechnen zu lassen. Diese würde ich dann in eine Variable speichern und und dann übergeben.

Code: Alles auswählen

from bottle import route, run, static_file, debug, response
from schnitt_test import schnittkraefte
s = schnittkraefte(3, 2.25, 26700000., 5, 10, 30, 10, 20, 20, 20)

@route('/')
@route('/index.html')
def index():
    return """
    <p><img src="bild.png" alt="Plot"></p>
    """
  
@route('/bild.png')
def plot_schnittkraefte(s):
    from plot import plot_schnittkraefte
    s = plot_schnittkraefte(s)
    response.headers['Content-Type'] = 'image/png'
    return s
  
debug(True)
run(host='localhost', port=8080)
Leider funktioniert das so nicht. Gibt es da einen Weg alle Werte im Vorfeld zu berechnen und diese dann zu übergeben ?

gruß
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Man könnte zum Beispiel die Bild-URL mit den gewünschten Parametern versehen.
Das Leben ist wie ein Tennisball.
Benutzeravatar
mathman
User
Beiträge: 92
Registriert: Mittwoch 19. November 2008, 08:27
Wohnort: Magdeburg
Kontaktdaten:

EyDu hat geschrieben:Man könnte zum Beispiel die Bild-URL mit den gewünschten Parametern versehen.
Meinst du damit, das ich mit dem Bild eine Dynamische Route erzeugen soll?
Das Problem dabei ist, dass s eine 32 x 32 Matrix ist und man das sicherlich schlecht übergeben kann
frabron
User
Beiträge: 306
Registriert: Dienstag 31. März 2009, 14:36

So komplexe Datenstrukturen lassen sich eher schlecht übergeben, da in der HTTP - Welt nur Textdaten existieren. Du kannst also deine Matrix als String realisieren und der Plot-Funktion mittels POST unterjubeln (für GET ist der String dann wahrscheinlich zu lang), oder du berechnest in jeder Funktion deine Schnittkräfte neu. Diesen Weg würde ich auch vorschlagen, da so beide Funktionen entkoppelt sind und du die Plot-Funktion auch ohne HTML aufrufen kannst.

Du kannst dann ja deine Parameter (3, 2.25, 26700000., 5, 10, 30, 10, 20, 20, 20) entweder als GET Parameter der URL anhängen, oder wie EyDu vorschlägt, als URL Parameter

Code: Alles auswählen

from bottle import url

@route('/details/param1/:param1/param2/:param2/....')
def details(param1, param2, ....):
    # mach was
    schnittkraefte(param1, param2, ....)
    return '<img src="{url}">'.format({'url': url(plot, param1, param2, ....)})

@route('/plot/param1/:param1/param2/:param2/....')
def plot(param1, param2, ....):
    # plotte was


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

Das Problem ist, dass um die Eingangswerte für die Funktion Schnittkräfte noch zahlreiche Funktionen vor geschallten werden müssen um diese zu erhalten :roll:

Hier zum Beispiel wird automatisch nen Spruch generiert. Das Muster für das Bild sieht wie folgt aus:

http://www.sloganizer.net/bild,Python,orange,blau.png

Demnach wird mit Sicherheit eine Funktion dahinter stehen, die mittels "," den Namen trennt und daraus die Werte zur weiteren Verarbeitung generiert.

Könnte man dann nicht wie folgt vorgehen :D

<img src="{url}/4/1,2,3,4/1,2,3,4/1,2,3,4/1,2,3,4"/>

der erste Parameter bedeutet, dass es sich um eine 4 x 4 Matrix handelt.
Danach werden die weiteren Parameter zerlegt, da durch "," getrennt.
Im darauf folgenden Schritt wird dann aus den Werten eine 4 x 4 Matrix gemacht.
Dadurch habe ich dann wieder eine 4 x 4 Matrix. Ist so was möglich oder völliger Quatsch ?
frabron
User
Beiträge: 306
Registriert: Dienstag 31. März 2009, 14:36

Probier's doch mal aus ;)
Benutzeravatar
mathman
User
Beiträge: 92
Registriert: Mittwoch 19. November 2008, 08:27
Wohnort: Magdeburg
Kontaktdaten:

So, hab mir da mal was zusammen geschrieben,
funktioniert aber leider nicht :K

Code: Alles auswählen

from bottle import route, run, static_file, debug, response, url

@route('/')
def index():
    pass

@route('/bild.png/:dim/:z1/:z2/:z3/:z4')
def plot_schnittkraefte(dim, z1, z2, z3, z4):
    matrix = []
    
    if dim == "4":
      #zerlgen von z1
      z1 = z1.split(',')
      #zerlegen von z2
      z2 = z2.split(',')
      #zerlegen von z3
      z3 = z3.split(',')
      #zerlegen von z4
      z4 = z4.split(',')
      #zusammfuegen zu Matrix
      matrix.append(z1)
      matrix.append(z2)
      matrix.append(z3)
      matrix.append(z4)
    
    from plot import plot_schnittkraefte
    
    s = plot_schnittkraefte(matrix)
    response.headers['Content-Type'] = 'image/png'
    return s
  
debug(True)
run(host='localhost', port=8080)
mit der Fehlermeldung
Traceback (most recent call last):
File "/home/mkoenig/workspace/sb2brain/src/web_test_matrix.py", line 7, in <module>
@route('/bild.png/:dim/:z1/:z2/:z3/:z4')
File "/home/mkoenig/workspace/sb2brain/src/bottle.py", line 460, in wrapper
self.routes.compile()
File "/home/mkoenig/workspace/sb2brain/src/bottle.py", line 355, in compile
raise RouteSyntaxError("Could not add Route: %s (%s)" % (route, e))
bottle.RouteSyntaxError: Could not add Route: <Route('bild.png/:dim/:z1/:z2/:z3/:z4') /> (redefinition of group name 'z' as group 4; was group 3)
Was mach ich denn falsch, hab mich eigentlich am Tutorial gehalten ...
Benutzeravatar
noisefloor
User
Beiträge: 4186
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,
Ist so was möglich oder völliger Quatsch ?
Ab einer bestimmten Komplexität der Parameter, die hier IMHO überschritten ist, sollte man lieber ein HTML-Seite (z.B. generiert aus einem Bottle-Template) mit einem HTML-Formular zur Dateneingabe vorschalten.

Gruß, noisefloor
Benutzeravatar
mathman
User
Beiträge: 92
Registriert: Mittwoch 19. November 2008, 08:27
Wohnort: Magdeburg
Kontaktdaten:

noisefloor hat geschrieben:Hallo,
Ist so was möglich oder völliger Quatsch ?
Ab einer bestimmten Komplexität der Parameter, die hier IMHO überschritten ist, sollte man lieber ein HTML-Seite (z.B. generiert aus einem Bottle-Template) mit einem HTML-Formular zur Dateneingabe vorschalten.

Gruß, noisefloor
Das soll ja auch geschehen. Der Nutzer gibt in einer Eingabemaske die Daten ein und der Server berechnet
dann die Ergebnisse, gibt diese dann in einem HTML Gerüst wieder aus.
Dazu sollen dann dynamisch Bilder (Plots aus mathplot) generiert werden. So wie ich das jetzt dem Thread entnommen habe, muss man das Bild in einer extra Route genieren lassen. Da sehr viele Berechnungen für den Pöot vorangehen möchte ich nicht 5 x die selben Berechnungen durchführen. Also muss ich der Route für den Plot doch irgendwie die Daten zum plotten übertragen ?!

Alternative wäre evtl. das Bild auf dem Server abzulegen. Problem dabei könnte aber sein, das die Berechnungen noch nicht abgeschlossen sind, ein zweiter Nutzer die Berechnungen startet und die Bilder dann vom ersten Nutzer vom zweiten überschrieben werden. Somit würde Nutzer 1 die Bilder vom Nutzer 2 erhalten :mrgreen:
Benutzeravatar
mathman
User
Beiträge: 92
Registriert: Mittwoch 19. November 2008, 08:27
Wohnort: Magdeburg
Kontaktdaten:

ich habe mir jetzt 2000 Zahlen die mit Kommata getrennt sind erzeugt.
Danach habe ich diese in der URL an gehangen

http://localhost:8080/bild/0,1,2,3,4,5,6....

Auf dem Server läuft dazu folgendes Skript

Code: Alles auswählen

from bottle import route, run, static_file, debug, response, url

@route('/')
def index():
    pass

@route('bild/:z')
def plot_schnittkraefte(z):
    
    #zerlgen von z
    z1 = z.split(',')

    return z1[1999]
  
debug(True)
run(host='localhost', port=8080)
Somit konnte ich mir den Wert von dem 1999 Element wieder geben.
Leider hat es nicht geklappt dass man mehrere dynamische Routen gleichzeitig nutzen kann,
aber hier könnte ich ja ein paar Infos zu dem String für die später Bearbeitung mitliefern, so dass z.B. der erste Wert die Dimension der Matrix ist. :mrgreen:
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Wieso übergibst Du die Daten nicht in einer Struktur, die sich vorher serialisieren lässt? Also als einfachstes eben als CSV-String, oder JSON, o.ä.? Damit hättest Du nur noch einen Parameter...
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
mathman
User
Beiträge: 92
Registriert: Mittwoch 19. November 2008, 08:27
Wohnort: Magdeburg
Kontaktdaten:

Guten Abend :mrgreen:

ich habe mir mal Json im Netz angeschaut und das klingt sehr viel versprechend :)
Leider komme ich noch nicht damit klar. Ich möchte mein Array in Json Encodieren lassen.

Code: Alles auswählen

In [69]: a = numpy.array([[4,5,6],[7,8,9]])

In [70]: a
Out[70]: 
array([[4, 5, 6],
       [7, 8, 9]])

In [71]: json.encoder("name", a)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)

/home/mkoenig/<ipython console> in <module>()

TypeError: 'module' object is not callable
Wenn ich die Dokus richtig interpretiere müsste daraus folgendes kommen
{
"typ" : "1",
"name" : [[4, 5, 6],
[7, 8, 9]]
}
und das ganze kann ich als string dann der route übergeben und dann sollte ein Modul mir das wieder entpacken.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Ich bin mir nicht sicher ob ``json`` mit Numpy-Arrays zurechtkommt, vermutlich musst du diese in Listen konvertieren.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Du suchst wohl auch eher "json.dump()", bzw "dumps()"!
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
mathman
User
Beiträge: 92
Registriert: Mittwoch 19. November 2008, 08:27
Wohnort: Magdeburg
Kontaktdaten:

Ich verstehe es leider immer noch nicht :K

Als erstes wandle ich ich erst mal mein Array in eine Liste um,
das klappt schon einmal

Code: Alles auswählen

In [23]: a = numpy.array([[1,2],[3,4]])

In [24]: type(a)
Out[24]: <type 'numpy.ndarray'>

In [25]: s = a.tolist()

In [26]: type(s)
Out[26]: <type 'list'>

In [35]: y = json.dumps({'type': '1', 'ecz': s})

In [36]: y
Out[36]: '{"type": "1", "ecz": [[1, 2], [3, 4]]}'

In [37]: type(y)
Out[37]: <type 'str'>
Wenn ich das richtig verstehe, dann muss ich die Daten nach dem Schema nach [36] übergeben damit die Funktion das bearbeiten kann. Raus würde nun ein String kommen. Den hänge ich dann bei der dynamischen Route an. Wie wandle ich denn das ganze dann wieder zurück, so dass ich mir type und ecz ausgeben lassen kann um das wieder z.B. als Array umzuwandeln und ist soweit meine Denkweise richtig ?

gruß
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

mathman hat geschrieben: Wenn ich das richtig verstehe, dann muss ich die Daten nach dem Schema nach [36] übergeben damit die Funktion das bearbeiten kann. Raus würde nun ein String kommen. Den hänge ich dann bei der dynamischen Route an. Wie wandle ich denn das ganze dann wieder zurück, so dass ich mir type und ecz ausgeben lassen kann um das wieder z.B. als Array umzuwandeln und ist soweit meine Denkweise richtig ?
Denkweise sollte so weit richtig sein, wie ich es verstanden habe. Zur Deserialisierung: Schau doch einfach in die Doku von JSON ;-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
mathman
User
Beiträge: 92
Registriert: Mittwoch 19. November 2008, 08:27
Wohnort: Magdeburg
Kontaktdaten:

also ich glaube das loads die richtige Funktion ist :)

Code: Alles auswählen

In [57]: z = json.loads(y)

In [58]: type(z)
Out[58]: <type 'dict'>

In [59]: n = z['ecz']

In [60]: n
Out[60]: [[1, 2], [3, 4]]

In [61]: type(n)
Out[61]: <type 'list'>
Benutzeravatar
mathman
User
Beiträge: 92
Registriert: Mittwoch 19. November 2008, 08:27
Wohnort: Magdeburg
Kontaktdaten:

Super, es funktioniert :)

Im Vorfeld müssen die Hochkommata aus dem String den Json erzeugt entfernt und durch ein anderes Zeichen was ich durch das Web verschicken kann ersetzt werden. Gibt es da evtl. noch eine elegantere Herangehensweise ?

Code: Alles auswählen

s = ecz.tolist()
  y = json.dumps({'ecz': s})
  y = y.replace('\"', '@')
Dabei ist ecz meine 32 x 32 Matrix :mrgreen:

Code: Alles auswählen

from bottle import route, run, static_file, debug, response


@route('/')
@route('/index.html')
def index():
    
    return """
    <p><img src="bild.png/{@ecz@: [[0.0, 66.304347826099999, 0.0, -3.7317000000000002e-06, 0.0, 132.6086956522, 0.0, -7.4634999999999998e-06, 0.0, 15.2173913043, 0.0, 6.7850000000000005e-07, ......... 0.0, 0.0002282021, 0.0, 1.4492753623000001, 0.0, -3.6187000000000002e-06, -0.0]]}" alt="Plot"></p>
    """
  
@route('/bild.png/:string')
def plot_schnittkraefte(string):
    #from schnitt_mehrzwischenschritte import schnittkraefte
    #s = schnittkraefte(2, 2.25, 26700000., 10, 10, 10, 10, 20, 20, 20)
    import numpy, json
    
    string = string.replace("@", "\"")
    z = json.loads(string)
    z = z["ecz"]
    z = numpy.array(z)
    
    from plot import plot_schnittkraefte_min_max
    
    s = plot_schnittkraefte_min_max(z)
    response.headers['Content-Type'] = 'image/png'
    return s
  
debug(True)
run(host='localhost', port=8080)
Gruß
Antworten