[Anfänger] matplotlib & event

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
MB
User
Beiträge: 19
Registriert: Montag 5. Januar 2009, 15:07

Hallo,
ich habe einen code zusammengebastelt [ mehr war es wiklich noch nicht], der aber das tut, was er soll. Er zeichnet [Qt4] ein Diagramm, und stellt als rote Linie den Mittelwert und als Schatten die Standardabweichung dar.
Ich will jetzt einzelne Punkte durch anklicken entfernen - und das funktioniert auch. Das Dia wird neu gezeichnet und der engeklickte Punkt fehlt.Ich möchte aber auch den Mittelwert und die Standardabweichung neu zeichnen lassen oder wenigstens die aktaulisierten Werte neu ausgeben. Ich habe es pber suptitle und annotate probiert ging aber nicht.
Wer kann mir mit einem möglichst einfachen Trick helfen ?

Code: Alles auswählen

# -*- coding: utf-8 -*-
import numpy as np
from pylab import *
import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot(111)

AMF=[1.1665984021636808, 1.1738562738644749, 1.1666294668813255, 1.1662366918581406, 1.1651908070446064, 1.165288542617118, 1, 1.1640923694666732, 1.1659259361461558, 1.1664426493447293, 1.1608471516431171, 1.1637575882952071, 1.1664486807403549, 1.1657513460484836, 1.1658653494065288, 1.1652294264546637, 1.1637708502945607, 1.1663345388929887, 1.1657111410830556, 1.1642051230567771, 1.1662390490217216, 1.1666013478957822, 1.1658008125454429, 1.1650347331268238, 1.16564198694793, 1.1665620856481373, 1.1668473788099185, 1.1660328625855854, 1.1610649651775911, 1.1653362700554857, 1.1660170412195148, 1.1655608245908795, 1.1649259712436562, 1.1661034078279107, 1.1658982696612021, 1.1668618585373423, 1.1656182159347515, 1.1656959650201444, 1.1640673861171582, 1.1654065220319783, 1.1655201699714539, 1.1665113912410165, 1.16688065699758, 1.1647657324873133, 1.163811045130742, 1.1676441163241795, 1.1656978580420219, 1.1667022499421618, 1.1664803629149312, 1.1658037516041027, 1.165858238694983, 1.1647174579138215, 1.1662780731556455, 1.1656446099435747, 1.1650883035942274, 1.1661165869890884, 1.1659206314727075, 1.166902696643094, 1.1661546880797653, 1.1657264121094733, 1.1665309336729404, 1.1665729226785844, 1.1666769521004274, 1.1651938795447918, 1.1661139521205739, 1.1666619176848347, 1.1663125101453284, 1.1659946022790781, 1.1663324505243711, 1.1655818113200376, 1.1651646087485761, 1.1654872265597902, 1.1609014588599234, 1.1591316818841253, 1.1655163728421705, 1.1651404585669745, 1.1655457123658701, 1.1667826227502649, 1.1661540212475174, 1.1662195488460425, 1.1655385288211242, 1.1662038529234007, 1.1667568210500039, 1.1657906229354078, 1.1656151542230893, 1.1652421787338023, 1.1659248063085517, 1.1657503510030958, 1.1685389065793308, 1.1649006003773144, 1.1661831935475673, 1.1661591347866815, 1.1661377577061192, 1.1671946977000474, 1.1652594895141053, 1.1667013759125955, 1.1649293250788733, 1.1660873956546494, 1.1651507558969887, 1.1637579713799198, 1.166063100797625, 1.1659128144934174, 1.1663577615075276, 1.1655750805894571, 1.1663409591232059,  ]
ymin,ymax=min(AMF),max(AMF)
l=np.arange(len(AMF))
xmax=max(l)
ax.axis([0,xmax,ymin,ymax])
mu=mean(AMF)
sigma=std(AMF)
Test=ax.annotate("%s" %mu,xy=(10,-5), xycoords='axes points')
#fig.suptitle("MW = %.4f\nStd = %.4f" %(mu,sigma))
ax.axhline(mu,linewidth=1, color='r')
ax.axhspan(mu-sigma,mu+sigma,facecolor='0.5', alpha=0.5)
line, = ax.plot(AMF, 'o', picker=5)
a=""
def onpick(event):
    thisline = event.artist
    xdata = thisline.get_xdata()
    ydata = thisline.get_ydata()
    ind = event.ind
    #print 'onpick points:', (xdata[ind],ydata[ind])
    index=xdata[ind]
    del AMF[index]
    l=np.arange(len(AMF))
    line.set_ydata(AMF)
    line.set_xdata(l)
    xmax,ymin,ymax=max(l),min(AMF)-0.01,max(AMF)+0.01
    ax.axis([0,xmax,ymin,ymax])
    mu=mean(AMF)
    sigma=std(AMF)
    Test.update("%s" %mu)
    fig.suptitle("MW = %.4f\nStd = %.4f" %(mu,sigma))
    ax.axhline(mu,linewidth=1, color='r')
    ax.axhspan(mu-sigma,mu+sigma,facecolor='0.5', alpha=0.5)
    plt.draw()

fig.canvas.mpl_connect('pick_event', onpick)

plt.show()
Vielen Dank, MB
Benutzeravatar
gkuhl
User
Beiträge: 600
Registriert: Dienstag 25. November 2008, 18:03
Wohnort: Hong Kong

Einige zusaetzliche Zeilenumbrueche in Zeile 8 empfaende ich als unglaublich praktisch :wink:
INFACT
User
Beiträge: 385
Registriert: Freitag 5. Dezember 2008, 16:08

gkuhl hat geschrieben:Einige zusaetzliche Zeilenumbrueche in Zeile 8 empfaende ich als unglaublich praktisch :wink:
Bei mir ist es Zeile 9 :?: :wink:
Ich glaube du hast das falsch vertsanden...
gkuhl meinte es so:

Code: Alles auswählen

AMF=[
    1.1665984021636808, 1.1738562738644749, 1.1666294668813255,
    1.1662366918581406, 1.1651908070446064, 1.165288542617118,
    1, 1.1640923694666732, 1.1659259361461558, 1.1664426493447293, 
    [...]
]
:wink:
[b][i]ein kleines game für die die lust haben http://konaminut.mybrute.com[/i][/b]
;-)
MB
User
Beiträge: 19
Registriert: Montag 5. Januar 2009, 15:07

Hallo,
ich bin ein wenig eingetaucht und habe eine Lösung für mein Problem gefunden. Wen es interessiert:

Code: Alles auswählen

# -*- coding: utf-8 -*-
import numpy as np
from pylab import *
import matplotlib.pyplot as plt
AMF=[1.1665984021636808, 1.1738562738644749, 1.1666294668813255, 1.1662366918581406, 1.1651908070446064, 1.165288542617118, 1, 1.1640923694666732, 1.1659259361461558, 1.1664426493447293, 1.1608471516431171, 1.1637575882952071, 1.1664486807403549, 1.1657513460484836, 1.1658653494065288, 1.1652294264546637, 1.1637708502945607, 1.1663345388929887, 1.1657111410830556, 1.1642051230567771, 1.1662390490217216, 1.1666013478957822, 1.1658008125454429, 1.1650347331268238, 1.16564198694793, 1.1665620856481373, 1.1668473788099185, 1.1660328625855854, 1.1610649651775911, 1.1653362700554857, 1.1660170412195148, 1.1655608245908795, 1.1649259712436562, 1.1661034078279107, 1.1658982696612021, 1.1668618585373423, 1.1656182159347515, 1.1656959650201444, 1.1640673861171582, 1.1654065220319783, 1.1655201699714539, 1.1665113912410165, 1.16688065699758, 1.1647657324873133, 1.163811045130742, 1.1676441163241795, 1.1656978580420219, 1.1667022499421618, 1.1664803629149312, 1.1658037516041027, 1.165858238694983, 1.1647174579138215, 1.1662780731556455, 1.1656446099435747, 1.1650883035942274, 1.1661165869890884, 1.1659206314727075, 1.166902696643094, 1.1661546880797653, 1.1657264121094733, 1.1665309336729404, 1.1665729226785844, 1.1666769521004274, 1.1651938795447918, 1.1661139521205739, 1.1666619176848347, 1.1663125101453284, 1.1659946022790781, 1.1663324505243711, 1.1655818113200376, 1.1651646087485761, 1.1654872265597902, 1.1609014588599234, 1.1591316818841253, 1.1655163728421705, 1.1651404585669745, 1.1655457123658701, 1.1667826227502649, 1.1661540212475174, 1.1662195488460425, 1.1655385288211242, 1.1662038529234007, 1.1667568210500039, 1.1657906229354078, 1.1656151542230893, 1.1652421787338023, 1.1659248063085517, 1.1657503510030958, 1.1685389065793308, 1.1649006003773144, 1.1661831935475673, 1.1661591347866815, 1.1661377577061192, 1.1671946977000474, 1.1652594895141053, 1.1667013759125955, 1.1649293250788733, 1.1660873956546494, 1.1651507558969887, 1.1637579713799198, 1.166063100797625, 1.1659128144934174, 1.1663577615075276, 1.1655750805894571, 1.1663409591232059, 1.1674739157151257, 1.1656354037630032, 1.1669235584465472, 1.1665103115651907, 1.1660065430630397, 1.1660813002793833, 1.1658412635497026, 1.1659550429575429, 1.1664770871718584, 1.1663143964351674, 1.1657396544728182, 1.1648524445372461, 1.1654830615683938, 1.1658098447353684, 1.1660176923906562, 1.1653512183690182, 1.1641230266836058, 1.1668760909642637, 1.1641891029406513, 1.1667224873301649, 1.1654539943454676, 1.1672137687675492, 1.1655146263820904, 1.1650266380905654, 1.1655265507656001, 1.1656121418446852, 1.1653633223146957, 1.1677075633227183, 1.1656909311815653, 1.1676176077949842, 1.166022512537386, 1.165560921640387, 1.1653976922579916, 1.1663486926292934, 1.1656404685964941, 1.1640321760392955, 1.1569951346467899, 1.1639034628902676, 1.1658491380960907, 1.157805269264357, 1.1647445920098252, 1.1671216451854443, 1.1648383840848717, 1.1678449876878736, 1.1658837200170336, 1.1660288170728155, 1.165629393731537, 1.1660581801628007, 1.1657311538530652, 1.1678532156280823, 1.1651928456924083, 1.1658371079799419, 1.1628973178989142, 1.1652695282235301, 1.1661773376807838, 1.1661631317457815, 1.1653367255638523, 1.164868490881326, 1.167404055962318, 1.1579755919166315, 1.1665992608168423, 1.1649411971551122, 1.1660358307841578, 1.1642224170125568, 1.1653652405066968]
ymin,ymax=min(AMF),max(AMF)
l=np.arange(len(AMF))
xmax=max(l)
mu=mean(AMF)
sigma=std(AMF)
fig = plt.figure(1, facecolor="w")
ax = fig.add_subplot(111)
ax.axis([0,xmax,ymin,ymax])
line, = ax.plot(l,AMF, 'ro', picker=5)   

class PointDeleter:
    """
    Angeklickte Punkte werden aus dem Diagramm genommen und der Mittelwert 
    sowie die Standardabweichung neu berechnet und im Titel dargestellt.
    """
    def __init__(self):
        
        self.text=ax.text(0.05, 0.95, 'selected: %f'%mu,
                          transform=ax.transAxes, va='top')
        self.title=fig.suptitle("MW = %.4f\nStd = %.4f" %(mu,sigma))
        self.line, = ax.plot(l,AMF, 'go', picker=5)
        
    def onpick(self,event):
        
        xdata = line.get_xdata()
        ydata = line.get_ydata()
        
        # the click locations
        x = event.mouseevent.xdata
        y = event.mouseevent.ydata
        
        index=event.ind
        del AMF[index]
        print index
        
        self.amf=AMF
        self.update()
                       
    def update(self):
        
        AMF=self.amf
        ax.cla()
        
        l=np.arange(len(AMF))
        xmax,ymin,ymax=max(l),min(AMF)-0.01,max(AMF)+0.01
        ax.axis([0,xmax,ymin,ymax])
        
        self.line, = ax.plot(l,AMF, 'ro', picker=5)
        
        mu=mean(AMF)
        sigma=std(AMF)
                       
        ax.axhline(mu,linewidth=1, color='r')
        ax.axhspan(mu-sigma,mu+sigma,facecolor='0.5', alpha=0.5)
        self.title.set_text("MW = %.4f\nStd = %.4f" %(mu,sigma))
        fig.canvas.draw()
            
deleter=PointDeleter()    
fig.canvas.mpl_connect('pick_event', deleter.onpick)
plt.show()
Ein Problem habe ich nur noch mit dem Verändern von
self.text=ax.text(0.05, 0.95, 'selected: %f'%mu,
transform=ax.transAxes, va='top')
Hat vielleicht auch jemand noch eine Idee, wie ich die zuletzt gelöschten Punkte wieder zurückhole?
Gruß, MB
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Sehr relevante Lösungsvorschläge :roll:

@MB: Also 1. läuft Dein Beispiel bei mir nicht so doll und 2. solltest Du Dir vielleicht mal Pep8 anschauen und 3. kann man manche Dinge gut abkürzen und 4. schlage ich vor, Du schaust Dir mal die embedding_in_qt-Bespiele an. Letztere sind im Download enthalten. So, mal ans Eingemachte:

Statt

Code: Alles auswählen

ind = event.ind
    #print 'onpick points:', (xdata[ind],ydata[ind])
    index=xdata[ind]
    del AMF[index]
kannst Du z. B.

Code: Alles auswählen

AMF.pop(event.ind[0])
schreiben. Und auch an anderen Stellen kannst Du ordentlich kürzen, aber das kommt mit der Zeit ;-).

In 'onpick' würde ich als erstes 'plt.cla()' machen - Du willst ja Deinen neuen Plot nicht ständig mit dem vorhergehenden zusammenhaben, oder? Stattdessen habe ich mal im Schnelltest ein 'ax.plot(AMF, 'go', picker=5)' vor 'plt.draw()' gesetzt.

'Test.update("%s" %mu)' gibt bei mir ein Traceback, so funktioniert update nicht. Ähnliches gilt für 'fig.suptitle(...': Das sind a) "widgets", die als statische Texte gedacht sind. Wenn Du so etwas in einem dynamischen Plot nutzt, kann das sehr langsam werden, weil Du ständig löschen und Text plotten mußt. Und b) überschreibst Du im konkreten Fall diese "suptitles" und zwar, weil Text auf verschiedenen Ebenen geschrieben wird: ax und fig.
Das mit den verschiedenen Ebenen ist auch der Hauptgrund, warum ich Dir keine Gesamtlösung anbieten kann: Zu wenig Zeit dieses Ding komplett umzuschreiben, weil zu umständlich. Aber das ist auch egal, weil ich würde, wenn Du schon eine dynamische Darstellung willst, die Statusbar nehmen. Das geht schnell und Du mußt mit dem Text nicht im Plot rumfummeln.

HTH
Christian

PS Ach ja, den Sternchenimport würde ich auch sein lassen - gerade bei mpl, weil, solltest Du je numpy oder mpl unabhängig voneinander updaten, kannst Du in Teufelsküche kommen, wenn Du durch pylab-Sternchenimport auf numpy zurückgreifst. Gar nicht gut ;-).
PPS Und editiere wirklich bald Deinen ersten Post hier wie gewünscht, ist sonst ziemlich lästig.
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

War wohl gerade etwas zu spät ...

Bitte benutze doch ein Pastbin - sonst wird es schnell unmöglich Dir überhaupt zu antworten - und breche die Rohdaten um, sonst ist es wirklich lästig Dir zu antworten.

Und der Code sieht jetzt schon viel aufgeräumter aus! Und die Lösung für den Text sieht gut aus!

Und was ist jetzt noch Dein Problem? Da ist wohl was verschluckt worden.

Gruß,
Christian
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Was das Zurückholen gelöschter Punkte betrifft: So wie Du es jetzt machst, hast Du schon die halbe Arbeit gemacht - jetzt noch mein Beispiel mit dem pop() umsetzen. pop() gibt den gepoppten Wert zurück. Den kannst Du in einer separaten Liste / ndarray speichern und ggf. wieder plotten. Fallst Du die Indexwerte benutzen möchtest, kannst Du auch ein dict {index: wert} anlegen, aus dem Du Deine Ursprungsliste mittels insert() regenerierst. Das Tutorial bespricht die Listenmethoden ausführlich ;-)

HTH
Christian
Antworten