Benutzer-Werkzeuge

Webseiten-Werkzeuge


Seitenleiste

codes

schallwerkzeuge.py

#!/usr/bin/python
# coding=utf8
## Verhalten von / wie in Python 3    a/b  = float
 
from __future__ import division
from math import pi
 
### Audio-Module
 
import pyaudio
from scipy.io import wavfile
 
###  Fourier, Numerik
 
import numpy.fft as FFT
import numpy as np
 
 
##############
 
# Graphik
 
import matplotlib.pyplot as plt
 
 
###
 
CHANNELS=1
RATE=44100
DAUER=1
ANZAHL=DAUER*RATE # ANZAHL der Frames,
 
# globale Variablen, schlechter Programmierstil, hier aber ganz
# praktisch: Nach Aufnahme oder Lesen werden diese Variablen 
# entsprechend gesetzt.
 
 
def recordsnd(filename, time):
	'''
	Nimmt eine  time  Sekunden lange Schallsequenz
	auf (mit der Samplerate 48000 Hz) auf und speichert,
	speichert sie in der Datei filename und gibt die
	Aufnahme als numpy-array mit Werten zwischen -1 und 1 zurück
	'''
	global ANZAHL
	global RATE
	global DAUER
	global CHANNELS 
 
	DAUER=time
	ANZAHL=int(RATE*DAUER)
 
 
	p = pyaudio.PyAudio()
	raw_input("Aufnehmen  "+str(time)+ " Sekunden): Eingabetaste drücken...")
 
	stream = p.open(format =pyaudio.paInt16 ,
                channels = CHANNELS,
	                rate = RATE,
	                input = True,
	                frames_per_buffer = 1024)#ANZAHL)
 
 
	yy=stream.read(ANZAHL)
	y=np.fromstring(yy,dtype=np.short)
	if CHANNELS==2:
		y=y.reshape((y.shape[0]//2,2))
 
	print("Aufgenomen: " + str(ANZAHL) + " Frames")
	stream.close()
	p.terminate()
	yy=np.array(y,dtype='d')/32768.0
	if filename!=None:
		wavwrite(filename, yy)
 
	return yy
 
 
def wavwrite(filename, y):
	'''Schreibt ein wav-File aus einem numpy-array'''
	wavfile.write(filename, RATE, np.array(y*2**15, dtype=int))
 
 
def wavread(filename):
	'''Liest ein wav-File in ein numpy-Array'''
	global ANZAHL
	global RATE
	global DAUER
	global CHANNELS 
 
	RATE,y=wavfile.read(filename)
	ANZAHL=y.shape[0]
	if len(y.shape)==2:
		CHANNELS=y.shape[1]
	else:
		CHANNELS=1
	DAUER=ANZAHL/RATE
 
	return np.array(y,dtype=np.float)/2**15
 
 
 
 
 
def playsnd(y, r):
	'''
	spielt das numpy-array (bzw. Vektor) y als Klang 
	mit der Samplerate r  [Hz] ab.
	'''
	def callback(in_data, frame_count, time_info, status):
		data = (32767*klanggen.generate(frame_count/RATE)).astype(np.int16)
		return (data.copy(), pyaudio.paContinue)
 
 
	p = pyaudio.PyAudio()
 
	CHUNK=2**12
 
	stream = p.open(format =pyaudio.paInt16 ,
			channels = CHANNELS,
			rate = r,
			output = True,
			frames_per_buffer=CHUNK)
			#callback=callback)#ANZAHL)
 
 
	yy=np.array(y.flatten()*2**15,dtype=np.short)
	for i in range(0,len(yy),CHUNK):
		stream.write(yy[i:i+CHUNK].tostring(order='F'))
	stream.close()
	p.terminate()
 
 
 
def inspectsnd(y):
	'''Zeigt einen Plot von y'''
 
	n=y.shape[0]
	fig=plt.Figure(figsize=(6,4),dpi=100)
	ax=fig.add_subplot(111)
	x=np.arange(0,n,1)/np.float32(RATE)
	plt.plot(x,y)
 
	plt.show()
 
 
 
def inspectspec(y):
	'''zeigt einen Plot des DFT-Spektrums von y'''
	global RATE
 
	#  Vorbereitungen, um ein Fenster zum Plotten zu kriegen
	plt.figure(1)
 
	n=len(y)
	window=np.blackman(n)
	sumw=sum(window*window)
 
	A=FFT.fft(y*window) 
	B2=(A*np.conjugate(A)).real
	sumw*=2.0   
	sumw/=1/np.float(RATE)  # sample rate
	B2=B2/sumw
 
 
	x=np.arange(0,n/2,1)/np.float(n)*RATE
 
 
	eps=1e-8
	plt.plot(x, np.log10(B2[0:n/2]+eps))
	plt.show()
 
def sinewave(f,r,d):
	'''erzeugt die Daten einer Sinusschwingung mit Frequenz f, Dauer d
	und Samplerate r'''
	global RATE
	global DAUER
	global ANZAHL
 
	RATE=r
	DAUER=d
	ANZAHL=DAUER*RATE
	y=np.zeros(r*d)
	for i in range(0,r*d):
		y[i]=np.sin(2*pi*f*i/float(r))
	return y
 

fouriersb.py

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

microlistener.py

#!/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

microlistenerdftnew.py

#!/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)
 

moving_circles.py

# -*- 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()
 
 
codes.txt · Zuletzt geändert: 2017/04/07 14:15 von beate_jung-mint1997