Benutzer-Werkzeuge

Webseiten-Werkzeuge


codes

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen gezeigt.

Link zu dieser Vergleichsansicht

codes [2017/04/07 14:05]
beate_jung-mint1997 angelegt
codes [2017/04/07 14:15] (aktuell)
beate_jung-mint1997
Zeile 190: Zeile 190:
   
 </​code>​ </​code>​
 +
 +====== fouriersb.py ======
 +<code python>
 +from __future__ import division
 +# -*- coding: utf-8 -*-
 +import scipy
 +import numpy.fft as FFT
 +
 +import matplotlib.pyplot as plt
 +from matplotlib.ticker import FormatStrFormatter
 +
 +execfile("​schallwerkzeuge.py"​)
 +
 +def calc_hamming_weights(T,​fs,​framesamp,​ hopsamp):
 + halfwindow=framesamp//​2
 + x=scipy.zeros(int(T*fs))
 + w = scipy.hamming(framesamp)
 +
 + for i in range(halfwindow,​ len(x)-halfwindow,​ hopsamp):
 + x[i-halfwindow:​i+halfwindow+1] += w
 +
 + for i in range(0,​int(T*fs)):​
 + if x[i]!=0:
 + x[i]=1./​x[i]
 + else:
 + x[i]=1.
 + return x
 +
 +
 +
 +def stft(x, fs, framesz, hop):
 +    """​Short time Fourier transformation:​ stft(x, RATE, fensterdauer,​ fensterverschiebung)
 +    Berechnet die diskrete Fourier-Transformation jeweils von einem Signalstück der
 +    Dauer "​fensterdauer"​. Die betrachteten Stücke sind jeweils um "​fensterverschiebung"​
 +    gegeneinander verschoben. ​
 +
 +    Vor der Transformation werden sie mit einem Hamming-Window multipliziert.
 +
 +    Die Funktion liefert ein Array zurück, dessen Zeilen die einzelnen Fouriertransformationen
 +    enthalten.
 +    """​
 +    #x=x.copy()
 +    halfwindow = int(framesz*fs/​2)
 +    framesamp=2*halfwindow+1
 +    hopsamp = int(hop*fs)
 +    w = scipy.hamming(framesamp)
 +    ​
 +    X = scipy.array([scipy.fft(w*x[i-halfwindow:​i+halfwindow+1]) ​
 +                     for i in range(halfwindow,​ len(x)-halfwindow,​ hopsamp)]) ​                    
 +    return X
 +
 +def istft(X, fs, T, hop):
 +    """​ istft(X, RATE, DAUER, fensterverschiebung)
 +
 +    Umkehrung von stft, nicht ganz perfekt.
 +    Interpretiert die Matrix X so, dass die Zeilen ​
 +    die Fouriertransformierte von Stücken enthalten,
 +    die jeweils um "​fensterverschiebung"​ gegeneinander ​
 +    verschoben sind.
 +    """​
 +    print fs, T, int(T*fs)
 +    x = np.zeros(int(T*fs),​dtype=np.complex)
 +    framesamp = X.shape[1]
 +    halfwindow=framesamp//​2
 +    hopsamp = int(hop*fs)
 +    w=calc_hamming_weights(T,​fs,​framesamp,​hopsamp)
 +    #ww = scipy.hamming(framesamp)
 +    #for i in range(len(ww)):​
 + #​ try: ​
 + #​ ww[i]=1./​ww[i]
 + # except:
 + #​ ww[i]=1.
 +
 +    #print "​halfwindow " , halfwindow, " ​ hopsamp ", hopsamp , "​len(x)",​ len(x)
 +    for n,i in enumerate(range(halfwindow,​ len(x)-halfwindow,​ hopsamp)):
 + #print "n: ",n, "i: ", i#print len(FFT.ifft(X[n]))
 + #print len(x[i-halfwindow:​i+halfwindow+1])
 + x[i-halfwindow:​i+halfwindow+1] += scipy.ifft(X[n])
 +        ​
 +    return x*w
 +
 +
 +def ersterplot(filename):​
 + global DAUER
 + global RATE
 + global ANZAHL
 +
 + sig=wavread(filename)
 +
 +
 + plt.subplot(2,​2,​1)
 + timescale=linspace(0,​DAUER,​len(sig))
 + plt.plot(timescale,​sig)
 + plt.xlabel("​Zeit [s]")
 + plt.ylabel("​Amplitude des Signals"​)
 + plt.title("​Das Signal"​)
 +
 + plt.subplot(2,​2,​2)
 + plt.plot(timescale,​scipy.bartlett(len(sig)))
 + plt.xlabel("​Zeit [s]")
 + plt.ylabel("​Faktor"​)
 + plt.title("​Das Bartlett-Fenster"​)
 + 
 + sigf=FFT.fft(sig)
 + plt.subplot(2,​2,​3)
 + frqscale=linspace(0,​len(sig)/​DAUER,​ len(sig))
 + plt.plot(frqscale,​np.abs(sigf))
 + plt.xlabel("​Frequenz [Hz]")
 + plt.ylabel("​Amplitude ")
 + plt.title("​Das Spektrum"​)
 +
 + w=scipy.bartlett(len(sig))
 + sigfhanning=FFT.fft(w*sig)
 + plt.subplot(2,​2,​4)
 + plt.plot(frqscale,​np.abs(sigfhanning))
 + plt.xlabel("​Frequenz [Hz]")
 + plt.ylabel("​Amplitude ")
 + plt.title("​Spektrum mit Bartlett-Fenster"​)
 + plt.show()
 +
 +def zweiterplot():​
 + # hier nun wird etwas ausprobiert,​ das Ihr letztes Mal
 + # angesprochen habt: Immer in kleinen Zeitintervallen ​
 + #  das Spektrum berechnen
 +
 + global DAUER
 + global RATE
 + global ANZAHL
 +
 +
 + fensterdauer=0.2
 + fensterueberlappung=0.05 ​  # jeweils in Sekunden
 +
 + sig=wavread("​lala.wav"​)
 + A=stft(sig,​RATE,​fensterdauer,​fensterueberlappung)
 + rsig=istft(A,​RATE,​DAUER,​fensterueberlappung)
 +
 + eps=1e-8 ​  # ​ Offset, um logarithmieren zu koennen
 +
 + r,​s=A.shape
 + yl=linspace(0,​DAUER,​ r)
 + xl=linspace(0,​RATE/​2,​s/​2)
 + X,​Y=meshgrid(xl,​yl)
 +
 + plt.figure(1)
 + plt.pcolor(X,​Y,​np.log10(np.absolute(A[:,:​s/​2]+eps)))
 + plt.show()
 +
 +def dritterplot():​
 + global DAUER
 + global RATE
 + global ANZAHL
 +
 + # Hier vergleichen wir die Rekonstruktion mit dem 
 + # ursprünglichen Signal
 +
 + fensterdauer=0.2
 + fensterueberlappung=0.05 ​  # jeweils in Sekunden
 +
 + sig=wavread("​lala.wav"​)
 + A=stft(sig,​RATE,​fensterdauer,​fensterueberlappung)
 + rsig=istft(A,​RATE,​DAUER,​fensterueberlappung)
 +
 +
 + plt.subplot(2,​1,​1)
 + plt.plot(np.abs(sig))
 +
 + plt.subplot(2,​1,​2)
 + plt.plot(np.abs(rsig))
 + print len(sig), len(rsig)
 + plt.show()
 +
 +
 +def vierterplot(fensterdauer=0.2,​fensterueberlappung=0.05):​
 + global DAUER
 + global RATE
 + global ANZAHL
 +
 + #
 + #  Heisenbergsche Unschärferelation
 + #
 +
 + sig=np.append(sinewave(200,​RATE,​1),​sinewave(500,​RATE,​1))
 + DAUER=2
 + A=stft(sig,​RATE,​fensterdauer,​fensterueberlappung)
 +
 + jump=int(fensterdauer/​2*RATE/​(DAUER/​fensterueberlappung))
 + eps=1e-8 ​  # ​ Offset, um logarithmieren zu koennen
 +
 + r,​s=A.shape
 + yl=linspace(0,​DAUER,​ r)
 + xl=linspace(0,​RATE/​2,​s/​2)
 + X,​Y=meshgrid(xl,​yl)
 +
 + plt.figure(1)
 + plt.pcolor(X,​Y,​np.log10(np.absolute(A[:,:​s/​2]+eps)))
 + plt.show()
 +
 +
 +
 +def fuenfterplot():​
 + global DAUER
 + global RATE
 + global ANZAHL
 +
 +
 + fensterdauer=0.2
 + fensterueberlappung=0.05 ​  # jeweils in Sekunden
 + eps=1e-8 ​  # ​ Offset, um logarithmieren zu koennen
 +
 + #
 + #  Nun die Spektren von i und a zum Vergleich
 + #
 +
 + sig1=wavread("​a.wav"​)
 + A1=stft(sig1,​RATE,​fensterdauer,​fensterueberlappung)
 + sig2=wavread("​i.wav"​)
 + A2=stft(sig2,​RATE,​fensterdauer,​fensterueberlappung)
 +
 + r,​s=A1.shape
 + yl=linspace(0,​DAUER,​ r)
 + xl=linspace(0,​RATE/​2,​s/​2)
 + X,​Y=meshgrid(xl,​yl)
 +
 + plt.subplot(2,​1,​1)
 + plt.pcolor(X,​Y,​np.log10(np.absolute(A1[:,:​s/​2]+eps)))
 +
 + r,​s=A2.shape
 + yl=linspace(0,​DAUER,​ r)
 + xl=linspace(0,​RATE/​2,​s/​2)
 + X,​Y=meshgrid(xl,​yl)
 +
 + plt.subplot(2,​1,​2)
 + plt.pcolor(X,​Y,​np.log10(np.absolute(A2[:,:​s/​2]+eps)))
 +
 + plt.show()
 +
 +if __name__=="​__main__":​
 +
 + ersterplot("​zweisignale.wav"​)
 + #​ersterplot("​nochzweisignale.wav"​)
 +
 +
 + #​zweiterplot()
 +
 + #​dritterplot()
 +
 + #​vierterplot(fensterdauer=0.2,​ fensterueberlappung=0.05)
 + #​vierterplot(fensterdauer=0.05,​ fensterueberlappung=0.02)
 +
 + #​fuenfterplot()
 +
 + ###  jetzt wärt ihr dran
 +
 +
 +
 +</​code>​
 +====== microlistener.py ======
 +
 +<code python>
 +#​!/​usr/​bin/​python
 +# coding=utf8
 +
 +from __future__ import division
 +
 +import pyaudio
 +import time
 +
 +
 +### Diese Klasse wird im Modul microlistener definiert.
 +### Sie kann in allen Projekten verwendet werden, die eine
 +### kontinuierliche Audio-Eingabe brauchen.
 +
 +
 +class MicroListener(object):​
 + def __init__(self,​rate,​channels,​chunk,​callback,​playback=False):​
 + '''​kreiert einen Stream, der mit der Samplerate '​rate'​
 + und '​channels'​ Kanälen über das Microphon Audio aufnimmt.
 + Nach jeweils '​chunk'​ Frames wird die callback-Funktion
 + aufgerufen. ​
 +
 + Falls playback==True,​ werden die Daten an den Lautsprecher
 + durchgereicht.
 +
 + Die Callback-Funktion nimmt als Argumente ​
 +
 + (in_data, frame_count,​ time_info, status)
 +
 + und gibt ein Tupel zurück, dessen erster Eintrag die
 + Daten (für Playback), dessen zweiter Eintrag ein Signal
 + ist, sollte pyaudio.paContinue sein.
 +
 + Also z. B. (mit einer globalen Variable CHANNELS)
 +
 +
 + def micro_callback(in_data,​ frame_count,​ time_info)
 + y=np.fromstring(in_data,​dtype=np.short)
 + if CHANNELS==2:​
 + y=y.reshape((y.shape[0]//​2,​2))
 + else:
 + y=y.reshape((y.shape[0],​1))
 + ##  y enthält danach die Daten des letzten Abschnitts
 + ##  aus chunk samples.
 + ## jetzt irgendwas mit den Daten machen
 + ##
 + return (in_data, pyaudio.paContinue)
 + '''​
 +
 + self.p = pyaudio.PyAudio()
 + self.stream = self.p.open(format=pyaudio.paInt16 ,
 +                channels=channels,​
 +                rate=rate,
 +                input=True,
 +                output=playback,​
 +                stream_callback=callback,​
 +                frames_per_buffer=chunk)
 +
 + self.stream.start_stream()
 + time.sleep(0.5)
 +
 + def __del__(self):​
 + self.stream.stop_stream()
 + self.stream.close()
 + self.p.terminate()
 +
 +
 +#########################################################################​
 +###  Test-Sektion #######################################################​
 +#########################################################################​
 +
 +
 +
 +if __name__=='​__main__':​
 +
 + import numpy as np
 +
 + ###########################​
 +
 + ### GLOBALE VARIABLEN
 +
 + CHANNELS=2
 + RATE=44100
 + CHUNK=2**11
 +
 +
 + def micro_callback(in_data,​ frame_count,​ time_info,​status):​
 + '''​callback Funktion: wird vom PyAudio-Objekt aufgerufen,
 + wenn CHUNK Frames von der Soundkarte (Mikrophon) gelesen wurden'''​
 + y=np.array(np.fromstring(in_data,​dtype=np.short),​dtype=np.float)
 + if CHANNELS==2:​
 + y=y.reshape((y.shape[0]//​2,​2))
 + else:
 + y=y.reshape((y.shape[0],​1))
 + print int(np.linalg.norm(y[:,​0])/​2000.)*'​*'​
 + return (in_data, status)
 +
 + listen=MicroListener(RATE,​CHANNELS,​CHUNK,​micro_callback)
 + while True:
 + pass
 +
 +</​code>​
 +
 +====== microlistenerdftnew.py ======
 +<code python>
 +#​!/​usr/​bin/​python
 +# coding=utf8
 +
 +from __future__ import division
 +
 +import pyaudio
 +import time
 +
 +
 +### Diese Klasse wird im Modul microlistener definiert.
 +### Sie kann in allen Projekten verwendet werden, die eine
 +### kontinuierliche Audio-Eingabe brauchen.
 +
 +
 +class MicroListener(object):​
 + def __init__(self,​rate,​channels,​chunk,​callback,​playback=False):​
 + '''​kreiert einen Stream, der mit der Samplerate '​rate'​
 + und '​channels'​ Kanälen über das Microphon Audio aufnimmt.
 + Nach jeweils '​chunk'​ Frames wird die callback-Funktion
 + aufgerufen. ​
 +
 + Falls playback==True,​ werden die Daten an den Lautsprecher
 + durchgereicht.
 +
 + Die Callback-Funktion nimmt als Argumente ​
 +
 + (in_data, frame_count,​ time_info, status)
 +
 + und gibt ein Tupel zurück, dessen erster Eintrag die
 + Daten (für Playback), dessen zweiter Eintrag ein Signal
 + ist, sollte pyaudio.paContinue sein.
 +
 + Also z. B. (mit einer globalen Variable CHANNELS)
 +
 +
 + def micro_callback(in_data,​ frame_count,​ time_info)
 + y=np.fromstring(in_data,​dtype=np.short)
 + if CHANNELS==2:​
 + y=y.reshape((y.shape[0]//​2,​2))
 + else:
 + y=y.reshape((y.shape[0],​1))
 + ##  y enthält danach die Daten des letzten Abschnitts
 + ##  aus chunk samples.
 + ## jetzt irgendwas mit den Daten machen
 + ##
 + return (in_data, pyaudio.paContinue)
 + '''​
 +
 + self.p = pyaudio.PyAudio()
 + self.stream = self.p.open(format=pyaudio.paInt16 ,
 +                channels=channels,​
 +                rate=rate,
 +                input=True,
 +                output=playback,​
 +                stream_callback=callback,​
 +                frames_per_buffer=chunk)
 +
 + self.stream.start_stream()
 + time.sleep(0.5)
 +
 + def __del__(self):​
 + self.stream.stop_stream()
 + self.stream.close()
 + self.p.terminate()
 +
 +
 +#########################################################################​
 +###  Test-Sektion #######################################################​
 +#########################################################################​
 +
 +
 +
 +if __name__=='​__main__':​
 +
 + import numpy as np
 + import matplotlib.pyplot as plt
 + import scipy.fftpack
 +
 + plt.ion()
 + ###########################​
 +
 + ### GLOBALE VARIABLEN
 +
 + CHANNELS=1
 + RATE=44100
 + CHUNK=2**11
 +
 + fig,ax = plt.subplots(1,​1)
 + graf, = plt.plot(np.linspace(0.0,​ (2.0*RATE), CHUNK/​2),​(CHUNK//​2-1)*[0]+[100000]) ​
 +
 +
 + def micro_callback(in_data,​ frame_count,​ time_info,​status):​
 + '''​callback Funktion: wird vom PyAudio-Objekt aufgerufen,
 + wenn CHUNK Frames von der Soundkarte (Mikrophon) gelesen wurden'''​
 + y=np.array(np.fromstring(in_data,​dtype=np.short),​dtype=np.float)
 + yf = scipy.fftpack.fft(y)[:​CHUNK/​2]
 + xf = np.linspace(0.0,​ (2.0*RATE), CHUNK/2)
 + graf.set_data(xf,​np.abs(yf)) ​
 + #​plt.pause(0.001)
 + #​plt.show()
 + if CHANNELS==2:​
 + y=y.reshape((y.shape[0]//​2,​2))
 + else:
 + y=y.reshape((y.shape[0],​1))
 + #print int(np.linalg.norm(y[:,​0])/​2000.)*'​*'​
 + return (in_data, status)
 +
 + listen=MicroListener(RATE,​CHANNELS,​CHUNK,​micro_callback)
 + while True:
 + fig.canvas.draw()
 + plt.pause(0.001)
 +
 +</​code>​
 +
 +====== moving_circles.py ======
 +<code python>
 +# -*- coding: utf-8 -*-
 +# uses:
 +# code under Copyright (c) 2014, Vispy Development Team.
 +# Distributed under the (new) BSD License. See LICENSE.txt for more info.
 +#
 +# most of it: Copyright 2017, Stefan Born
 +#
 +# License: GPL, version 2
 +
 +'''​Package moving_circles provides two backends for drawing
 +and moving circles on a canvas. You select the backend by setting
 +the variable PREFERRED_BACKEND in the calling module to
 +either '​VISPY'​ or '​MATPLOTLIB'​.'''​
 +
 +from __future__ import division
 +
 +# Analyse code of importing file:
 +
 +import inspect, re
 +
 +try:
 +    filename =  inspect.getfile(inspect.currentframe().f_back)
 +    with open(filename,​ '​r'​) as f:
 +        importing_module = f.read()
 +    PREFERRED_BACKEND = re.search ("​PREFERRED\_BACKEND\s*=\s*['​\"​](?​P<​preferred>​\w*)['​\"​]",​ importing_module).group('​preferred'​) ​  
 +except:
 +    PREFERRED_BACKEND = '​MATPLOTLIB'​
 +
 +
 +# import depends on PREFERRED_BACKEND
 +
 +import sys
 +import numpy as np
 +import time
 +
 +AVAILABLE_BACKENDS = []
 +
 +try:
 +    from vispy import app, gloo, visuals, scene
 +    from vispy.visuals import transforms
 +    AVAILABLE_BACKENDS.append('​VISPY'​)
 +except:
 +    pass
 +    ​
 +try:
 +    import matplotlib
 +    matplotlib.use('​GTKAgg'​)
 +    from matplotlib.backends.backend_gtkagg import FigureCanvasGTKAgg as FigureCanvas
 +    import matplotlib.figure
 +    import matplotlib.patches
 +    import matplotlib.axes
 +    import gtk
 +    AVAILABLE_BACKENDS.append('​MATPLOTLIB'​)
 +except Exception as e:
 +    print e
 +    ​
 +if PREFERRED_BACKEND in AVAILABLE_BACKENDS:​
 +    BACKEND = PREFERRED_BACKEND
 +else:
 +    try:
 +        BACKEND = AVAILABLE_BACKENDS[0]
 +    except:
 +        raise Exception("​NO BACKEND AVAILABLE"​)
 +
 +print "​Backend:​ ", BACKEND
 +
 +
 +if BACKEND == '​VISPY':​
 +    class Canvas(scene.SceneCanvas):​
 +        '''​Canvas for drawing.
 +        Is created with a certain initial width and height.
 +        The coordinate system for Drawing (implemented:​ Circles) refers
 +        to xlim and ylim.
 +        ​
 +        :param width: integer, width of canvas
 +        :param height: integer, height of canvas
 +        :param xlim: tuple of float, limits of x-axis
 +        :param ylim: tuple of float, limits of y-axis'''​
 +        ​
 +        ​
 +        def __init__(self,​ height=800, width=800, xlim = (-1.,​1.),​ylim=(-1.,​1.)):​
 +            scene.SceneCanvas.__init__(self,​ keys='​interactive',​bgcolor='​w'​)
 +            self.size = (width,​height)
 +            self.original_size = self.size
 +            self.visuals = []
 +            self.xlim = xlim
 +            self.ylim = ylim
 +            self.center = (0,0)
 +            self.scale = (width/​(self.xlim[1]-self.xlim[0]),​ height/​(self.ylim[1]-self.ylim[0]))
 +            self.translate = ((-self.xlim[0])*self.scale[0],​(-self.ylim[0])*self.scale[1])
 +            self.transform = transforms.STTransform(
 +                scale = self.scale,
 +                translate = self.translate )
 +            self.show()
 +            self.set_current()
 +            self.action = lambda x,y:0
 +            self.objects = []
 +            self.app.create()
 +        ​
 +        def on_draw(self,​ ev):
 +            print "​ond"​
 +            gloo.set_clear_color(self.bgcolor)
 +            gloo.set_viewport(0,​ 0, *self.size)
 +            gloo.clear()
 +            for vis in self.visuals:​
 +                vis.draw(vis.tr_sys)
 +            ​
 +        def update_canvas(self):​
 +            '''​manually update canvas'''​
 +            self.app.process_events()
 +            self.update()
 +            ​
 +        def set_action(self,​action,​objects):​
 +            '''​registers an action to be performed on certain objects at each update
 +            :param action: ​ function (objects, event)
 +            :param objects: list of objects
 +            '''​
 +            ​
 +            self.action = action
 +            self.objects = objects
 +                    ​
 +        def on_timer(self,​ event):
 +            self.action(self.objects,​event)  ​
 +            self.update()
 +
 +        def on_resize(self,​event):​
 +            width, height = self.size
 +            self.scale = np.array((self.original_size[0]/​width*self.scale[0],​self.original_size[1]/​height*self.scale[1],​1,​1))
 +            self.transform = transforms.STTransform(
 +                scale = self.scale,
 +                translate = self.translate )
 +            for vis in self.visuals:​
 +                vis.transform = self.transform
 +                vis.tr_sys.visual_to_document = vis.transform
 +            self.original_size = self.size
 +            ​
 +                    ​
 +        def run(self):
 +            self.on_draw(None)
 +            time.sleep(1)
 +            self._timer = app.Timer(interval=0.05,​ connect=self.on_timer,​ start=True)
 +           
 +            ​
 +            ​
 +                ​
 +    class Circle(object):​
 +        ​
 +        def __init__(self,​ canvas, **params):
 +            self.params = dict( pos =canvas.center,​ radius = (0.1,0.1),
 +                                color=(0.2, 0.2, 0.8, 1),
 +                                border_color=(1,​ 1, 1, 1)
 +                                )
 +            for key in params:
 +                if key!='​radius':​
 +                    self.params[key] = params[key]
 +                else:
 +                    try:
 +                        self.params[key] = (params[key],​params[key])
 +                    except:
 +                        pass
 +                ​
 +            self.visual = visuals.EllipseVisual(**self.params)
 +            self.visual.transform = canvas.transform
 +            self.visual.tr_sys = transforms.TransformSystem(canvas)
 +            self.visual.tr_sys.visual_to_document = self.visual.transform
 +            self.canvas = canvas
 +            canvas.visuals.append(self.visual)
 +            ​
 +        def set_radius(self,​ r):
 +            self.visual.radius = (r,r)
 +        ​
 +        def move(self,​dx,​dy):​
 +            self.visual.pos = (self.visual.pos[0]+dx,​ self.visual.pos[1]+dy)
 +            ​
 +        def set_color(self,​ color):
 +            self.visual.color = color
 +
 +        ​
 +if BACKEND == '​MATPLOTLIB':​
 +    ​
 +    from collections import namedtuple
 +    Event = namedtuple("​Event",​("​dt",​ "​elapsed"​))
 +    ​
 +    class Canvas(object):​
 +        '''​Canvas for drawing.
 +        Is created with a certain initial width and height.
 +        The coordinate system for Drawing (implemented:​ Circles) refers
 +        to xlim and ylim.
 +        ​
 +        :param width: integer, width of canvas
 +        :param height: integer, height of canvas
 +        :param xlim: tuple of float, limits of x-axis
 +        :param ylim: tuple of float, limits of y-axis'''​
 +        ​
 +        def __init__(self,​ height=800, width=800, xlim = (-1,​1),​ylim=(-1,​1)):​
 +            self.figure = matplotlib.figure.Figure()
 +            self.figure.add_axes((0,​0,​1,​1))
 +            self.axes = self.figure.axes[0]
 +            self.canvas = FigureCanvas(self.figure)
 +            self.xlim = xlim
 +            self.ylim = ylim
 +            self.axes.set_xlim(xlim)
 +            self.axes.set_ylim(ylim)
 +            self.size = (width,​height)
 +            self.original_size = (width, height)
 +            self.gtkwin = gtk.Window()
 +            self.gtkwin.set_default_size(width,​ height)
 +            self.gtkwin.add(self.canvas)
 +            self.gtkwin.show_all()
 +            ​
 +            ​
 +            self.action = lambda x,y:0
 +            self.objects = []
 +            self.visuals = []
 +            self.center = (0,0)
 +            self.start_time = time.time()
 +            self.last_time = time.time()
 +            self.timer = self.canvas.new_timer(interval = 50)
 +            self.timer.add_callback(self.update)
 +            self.timer.start()
 +            self.canvas.mpl_connect('​resize_event',​ self.on_resize)
 +            ​
 +        ​
 +            ​
 +        def set_action(self,​action,​objects):​
 +            '''​registers an action to be performed on certain objects at each update
 +            :param action: ​ function (objects, event)
 +            :param objects: list of objects
 +            '''​
 +            ​
 +            self.action = action
 +            self.objects = objects
 +            ​
 +        def update(self):​
 +            now = time.time()
 +            self.action(self.objects,​Event(dt=now-self.last_time,​elapsed=now-self.start_time))
 +            self.last_time = now
 +            self.axes.figure.canvas.draw()
 +            ​
 +        def update_canvas(self):​
 +            '''​manually update canvas'''​
 +            self.update()
 +            ​
 +        def on_resize(self,​ ev):
 +            width = ev.width
 +            height = ev.height
 +            self.size = (width, height)
 +            self.xlim = ((self.xlim[0]-self.center[0])*width/​self.original_size[0]+self.center[0],​
 +                         ​(self.xlim[1]-self.center[0])*width/​self.original_size[0]+self.center[0])
 +            self.ylim = ((self.ylim[0]-self.center[1])*height/​self.original_size[1]+self.center[1],​
 +                         ​(self.ylim[1]-self.center[1])*height/​self.original_size[1]+self.center[1])
 +            self.original_size = self.size
 +            self.axes.set_xlim(self.xlim)
 +            self.axes.set_ylim(self.ylim) ​   ​
 +
 +        def run(self):
 +            ​
 +            gtk.main()
 +        ​
 +                ​
 +    class Circle(object):​
 +        ​
 +        def __init__(self,​ canvas, **params):
 +            self.params = dict( pos =canvas.center,​ radius = 0.1,
 +                                color=(0.2, 0.2, 0.8, 1),
 +                                border_color=(1,​ 1, 1, 1))
 +            for key in params:
 +                self.params[key] = params[key]
 +                ​
 +            self.visual = matplotlib.patches.Circle(self.params['​pos'​],​radius=self.params['​radius'​],​
 +                 ​facecolor=self.params['​color'​],​ edgecolor = self.params['​border_color'​])
 +            ​
 +            ​
 +            self.canvas = canvas
 +            self.canvas.axes.add_patch(self.visual)
 +            self.canvas.visuals.append(self.visual)
 +            ​
 +     
 +            ​
 +        def move(self,​dx,​dy):​
 +            self.visual.center = (self.visual.center[0]+dx,​ self.visual.center[1]+dy)
 +            ​
 +        def set_color(self,​ color):
 +            self.visual._facecolor = color
 +            ​
 +        def set_radius(self,​ r):
 +            self.visual.radius = r
 +    ​
 +
 +
 +def action(objects,​ event):
 +    dt, elapsed = event.dt, event.elapsed
 +    for i,circ in enumerate(objects):​
 +        circ.move(0.5*dt*np.sin(elapsed*(i+1)),​ 0.5*dt*np.cos(elapsed*(i+1)))
 +        circ.set_color( (np.abs(np.sin(elapsed*(i+1))),​np.abs(np.sin(elapsed*2*(i+1))),​ np.abs(np.sin(elapsed*3*(i+1))),​0.3) )
 +        ​
 +    ​
 +if __name__ == '​__main__':​
 +    print BACKEND
 +    win = Canvas() ​
 +    ​
 +    objects = []
 +    ​
 +    for i in range(10):
 +        circ = Circle(win, pos=(-0.6+0.05*i,​0),​ radius=0.1,​color = (1,​0,​0,​0.2))
 +        objects.append(circ)
 +        ​
 +    win.set_action(action,​ objects)
 +    win.run()
 +      ​
 + </​code> ​  
 +
   
  
codes.1491566706.txt.gz · Zuletzt geändert: 2017/04/07 14:05 von beate_jung-mint1997