wechseln des subplots

Plattformunabhängige GUIs mit wxWidgets.
Antworten
feldmaus
User
Beiträge: 284
Registriert: Donnerstag 12. Oktober 2006, 16:48

Hi Alle,

ich schreibe ein kleines Programm für meine Diplomarbeit wo ich 2 Graphen
mit matplotlib plotte will. Es darf also immer nur eines angezeigt werden.

Hat da Jemand ein Beispiel für mich wie man das anstellt.

In der Mailing List habe ich nur den Befehl,

Code: Alles auswählen

[self.figure.delaxes(a) for a in self.figure.get_axes()]
auf geschnappt, der zwar meinen Graphen entfernt, aber meine neue Grafik
wird nicht mehr angezeigt.

Zum erstellen eines subplots nutze ich,

Code: Alles auswählen

self.subplot1 = self.figure.add_subplot(211)
Wie würde man es richtig machen ?

Grüße Markus
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Hoi,

eine mögliche Lösung, die ich selber verwende, sieht so aus:

Ich habe einen Datensatz, der die "eigentlichen" Daten und transformierte Daten enthält. Je nachdem, was ich zeigen will, werden beide Plots oder nur je einer gezeigt.

Dazu:

1. Lasse Nutzer (auch Dich selbst) die Einstellung in einem Menü oder Dialogen vornehmen. Einstellungen können Eigenschaften des Frames sein (z. B. in Form eines settings-Dictionary).
2. Gib Deinem Hauptframe eine Plotting-Funktion:

Code: Alles auswählen

def plot_data(self):
        raw_plot(self)
        self.toolbar.update()
Das ist jetzt ein bißchen pseudocodeartig, soll aber nur verdeutlichen, dass Du zwei Dinge tun mußt: Den Plot updaten und die Toolbar (falls Du eine hast).
3. zur Funktion raw_plot (parent.settings['grid'] ist hier: Mit oder ohne Grid - True oder False):http://paste.pocoo.org/show/121432/ (ungetestet aus einem alten Projekt von mir gekürzt) Das Alles wird natürlich in ein eigenes Modul ausgelagert, damit der GUI-Code nicht noch mehr als nötig aufgebläht ist. Die Funktionsunterstriche sind Geschmackssache.
Ob Du parent.fig.clear() aufrufen mußt, hängt ein bißchen vom Fall ab, ist aber meist zu empfehlen.
4. _call_to_plotting_function sieht dann so aus:

Code: Alles auswählen

_call_to_plotting_function(parent, upper, lower=None):
, d. h. Du kannst im Code kontrollieren, ob ein zweiter Subplot besetzt werden muß. Je nach Fall, können natürlich auch unterschiedliche Funktionen aufgerufen werden: Die eine akzeptiert einen Subplot, die andere potentiell zwei. Ich mache beides - kommt halt drauf an.
In der Funktion kannst Du einfach die Subplots ansprechen: z. B. upper.errorbar(...)

HTH
Christian

PS Ist vielleicht ein wenig umständlich oder umfangreich, hat aber großes Potential, wenn man viele Einstellungen und Funktionen zum Plotten übersichtlich verwalten will.
feldmaus
User
Beiträge: 284
Registriert: Donnerstag 12. Oktober 2006, 16:48

Irgendwie lese ich mir deinen Text mehrmals durch und ich verstehe nichts. :-)

Also ich habe ein Hauptframe in dem habe ich radio Buttons erstellt, welche
meine methode changeAnalysis(self,event) aufrufen, je nachdem welche
id der Aufrufer hatte will ich dann die gewünschten subplots erstellen.
Daher habe ich 2 eigene draw methoden,
drawtransient()
drawhistogram()

Nun habe ich mir bis jetzt so beholfen, das ich meine alte Grafik lösche in dem ich
folgendes benutze,
[self.figure.delaxes(a) for a in self.figure.get_axes()]
Und danach rufe ich eines meiner draw methoden wieder auf.
Hier mal ein Ausschnitt meines codes,
http://pastebin.com/m63cb10b9

So wie Du das geschrieben hast muss ich meine alten subplots gar nicht löschen ?

Grüße Markus
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Was soll den diese Listcomprehension? Die gibt doch bestenfalls [None, None, ...] zurück, was Du aber gar nicht nutzt.

Versuche mal vor dem erneuten Plotten:

Code: Alles auswählen

self.fig.clear()
Und dann natürlich mußt Du neue subplots anlegen.

Gruß,
Christian
feldmaus
User
Beiträge: 284
Registriert: Donnerstag 12. Oktober 2006, 16:48

CM hat geschrieben:Versuche mal vor dem erneuten Plotten:

Code: Alles auswählen

self.fig.clear()
Und dann natürlich mußt Du neue subplots anlegen.n
Yipee, :-)

das war mein vorletzter Punkt, jetzt nur noch die Slider Elemente.

Vielen Dank und Grüße Markus
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Freut mich, aber laß Dir bitte sagen, dass der GUI-Code ziemlich grausam aussieht:

- Man setzt widget ids nicht händisch und muß auch nicht auf die id kontrollieren. Zum automatisierten Aufbau von Menüs habe ich mal was gepostet: http://www.python-forum.de/topic-6891.html
- Nochmal ausgeführt, was ich im ersten Post hiert versuchte zu sagen: Es ist besser die Eigenschaften der Plots irgendwo (per "Häckchenmenü" oder Dialog) zu setzen und die Plottingfunktion abfragen zu lassen welche Eigenschaften gewünscht sind. Auf diese Weise läßt sich nämlich Code viel leichter pflegen. Deine Funktionen gehen ja ein bißchen in diese Richtung.
- Außerdem ist es eine schlechte Idee in Funktionen builtins zu überschreiben. Tipp: Gerade beim Plotting wissenschaftlicher oder technischer Daten braucht man gelegentlich 'min' oder 'max' zum besseren Skalieren. ;-)
- Ich kann aus dem Code nicht lesen, was self.plots ist, aber ein += mit self.subplot schaut seeehr seltsam aus: Wieso hast Du überhaupt self.subplot, also subplots als Teil Deines Frames? Die sind doch schon Teil der Figure im Canvas und das widerrum ist Teil des Frames. Hier ist Refactoring dringend angeraten.

Also ehrlich gesagt, werde ich aus dem Codebeispiel nicht schlau. Deshalb ging ich auch nicht darauf ein und mäkel halt hinterher daran rum. Ich hoffe damit trete ich nicht auf Deine Füße und Du kannst ein paar der Tipps umsetzen.

Vielleicht ist Enthought Tool Suite, insbesondere Traits etwas für Dich: Das nutzt wx und damit kann man potentiell interaktive GUIs mit mpl-Plotting zusammenbauen. Die Suite ist gewissermassen schon optimiert und Du mußt nicht so viel per Hand bauen. Prinzipiell kann man dennoch damit flexibel sein, es kostet allerdings sehr viel Zeit sich da einzulesen, weshalb ich Applikationen denn doch lieber per Hand baue.

Gruß,
Christian
Antworten