Seite 1 von 1

[Anfänger] matplotlib & event

Verfasst: Montag 2. März 2009, 18:51
von MB
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

Verfasst: Dienstag 3. März 2009, 03:00
von gkuhl
Einige zusaetzliche Zeilenumbrueche in Zeile 8 empfaende ich als unglaublich praktisch :wink:

Verfasst: Dienstag 3. März 2009, 13:26
von INFACT
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:

Verfasst: Dienstag 3. März 2009, 23:26
von MB
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

Verfasst: Dienstag 3. März 2009, 23:36
von CM
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.

Verfasst: Dienstag 3. März 2009, 23:42
von CM
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

Verfasst: Dienstag 3. März 2009, 23:46
von CM
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