Commit MetaInfo

Revisão8d3cc81108428e682db91036632d23ad516561a1 (tree)
Hora2010-04-22 14:52:38
AutorHidehisa SHIOMI <pylaf@user...>
CommiterHidehisa SHIOMI

Mensagem de Log

sourceforge公開用に整理したコード

Mudança Sumário

Diff

diff -r 000000000000 -r 8d3cc8110842 COPYING
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/COPYING Thu Apr 22 14:52:38 2010 +0900
@@ -0,0 +1,26 @@
1+Copyright (c) 2010, Hidehisa Shiomi <pylaf@users.sourceforge.jp>
2+All rights reserved.
3+
4+Redistribution and use in source and binary forms, with or without
5+modification, are permitted provided that the following conditions are met:
6+
7+ o Redistributions of source code must retain the above copyright notice,
8+ this list of conditions and the following disclaimer.
9+ o Redistributions in binary form must reproduce the above copyright
10+ notice, this list of conditions and the following disclaimer in the
11+ documentation and/or other materials provided with the distribution.
12+ o Neither the name of the <ORGANIZATION> nor the names of its
13+ contributors may be used to endorse or promote products derived from
14+ this software without specific prior written permission.
15+
16+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26+POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff -r 000000000000 -r 8d3cc8110842 MANIFEST
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/MANIFEST Thu Apr 22 14:52:38 2010 +0900
@@ -0,0 +1,13 @@
1+COPYING
2+README
3+setup.py
4+examples/transmitter.py
5+src/PyLAF/__init__.py
6+src/PyLAF/components.py
7+src/PyLAF/framework.py
8+src/PyLAF/plotters.py
9+src/PyLAF/widgets.py
10+src/PyLAF/Wireless/Filters.py
11+src/PyLAF/Wireless/Transmitter.py
12+src/PyLAF/Wireless/Wireless.py
13+src/PyLAF/Wireless/__init__.py
diff -r 000000000000 -r 8d3cc8110842 Manifest.in
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Manifest.in Thu Apr 22 14:52:38 2010 +0900
@@ -0,0 +1,2 @@
1+include COPYING
2+recursive-include examples *.py
diff -r 000000000000 -r 8d3cc8110842 README
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/README Thu Apr 22 14:52:38 2010 +0900
@@ -0,0 +1,7 @@
1+Install:
2+
3+ $ tar xvfz PyLAF-0.1.tar.gz
4+ $ cd PyLAF-0.1
5+ $ python setup.py install
6+
7+See http://pylaf.sourceforge.jp/ for detailed information.
\ No newline at end of file
diff -r 000000000000 -r 8d3cc8110842 setup.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/setup.py Thu Apr 22 14:52:38 2010 +0900
@@ -0,0 +1,11 @@
1+from distutils.core import setup
2+setup(
3+ name='PyLAF',
4+ version='0.1.0a1',
5+ package_dir={'PyLAF' : 'src/PyLAF'},
6+ packages=['PyLAF'],
7+ description='Python Laboratory Application Framework',
8+ author='Hidehisa Shiomi',
9+ author_email='pylaf@users.sourceforge.jp',
10+ url='http://pylaf.sourceforge.jp',
11+ )
\ No newline at end of file
diff -r 000000000000 -r 8d3cc8110842 src/PyLAF/__init__.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/PyLAF/__init__.py Thu Apr 22 14:52:38 2010 +0900
@@ -0,0 +1,7 @@
1+"""\
2+PyLAF --- A laboratory application framework for Python
3+"""
4+from framework import *
5+from widgets import *
6+from plotters import *
7+from easy import *
diff -r 000000000000 -r 8d3cc8110842 src/PyLAF/easy.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/PyLAF/easy.py Thu Apr 22 14:52:38 2010 +0900
@@ -0,0 +1,92 @@
1+# coding: utf-8
2+
3+from numpy import array
4+from framework import Component, Port, Variable, Frame, iscontain
5+from framework import DoubleVar, IntVar, StringVar, BooleanVar
6+from widgets import GridPane, Menu
7+from inspect import getmembers, stack, getargvalues
8+import Tkinter
9+
10+class EasyComponent(Component):
11+ PLOTTER = None
12+ def __init__(self,master):
13+ Component.__init__(self,master)
14+ self.colcount = 0
15+ self._menu = None
16+ self.sig_out = Port(Variable(array([])))
17+ def gui(self,master,pltcnf={},cnf={},**kw):
18+ frm = Frame(master)
19+ if not self.PLOTTER == None:
20+ v = self.__class__.PLOTTER(frm,pltcnf); v.plot(); v.show(); v.pack()
21+ setattr(frm,'plotter',v)
22+ self.sig_out.insertlink(0,v.sig_in);
23+ o = EasyGrid(frm,self); o.pack()
24+ return frm
25+ def menu(self,master,cnf={},**kw):
26+ if self._menu == None:
27+ return None
28+ else:
29+ menu = EasyMenu(master,list=self._menu,cnf=cnf,**kw)
30+ return menu
31+
32+class EasyPort(Port):
33+ def __init__(self,variable,label=None,var=None,key=None):
34+ Port.__init__(self,variable);
35+ if label == None:
36+ self.label = ''
37+ else:
38+ self.label = label
39+ if var == None:
40+ if type(variable.get()) == float:
41+ self.tkvar = DoubleVar(self)
42+ elif type(variable.get()) == int:
43+ self.tkvar = IntVar(self)
44+ elif type(variable.get()) == bool:
45+ self.tkvar = BooleanVar(self)
46+ else:
47+ self.tkvar = StringVar(self)
48+ else:
49+ self.tkvar = var(self)
50+ if key == None:
51+ caller = self._caller()
52+ caller.colcount += 1
53+ self.sortkey = caller.colcount
54+ else:
55+ self.sortkey = key
56+ def _caller(self):
57+ '''
58+ 下記ブログに掲載されていたコードを使わせてもらった
59+ http://d.hatena.ne.jp/Kazumi007/20090914/1252915940
60+ '''
61+ try:
62+ framerecords = stack()
63+ framerecord = framerecords[2]
64+ frame = framerecord[0]
65+ arginfo = getargvalues(frame)
66+ return arginfo.locals['self'] if 'self' in arginfo.locals else None
67+ finally:
68+ del frame
69+ return None
70+
71+class EasyGrid(GridPane):
72+ def __init__(self,master,component,cnf={},**kw):
73+ GridPane.__init__(self,master,cnf,**kw)
74+ ms = getmembers(component,lambda x:iscontain(x,EasyPort))
75+ ms.sort(lambda x,y:cmp(x[1].sortkey,y[1].sortkey))
76+ for m,o in ms:
77+ self.entry(o.label,o.tkvar)
78+ # self.append(o.label,Entry(self,textvariable=o.tkvar))
79+
80+class EasyMenu(Menu):
81+ def __init__(self,master=None,list=None,cnf={},**kw):
82+ Menu.__init__(self,master,cnf,**kw)
83+ for m in list: self.add_children(self,m)
84+ def add_children(self,parent,children):
85+ if type(children[1]) == list:
86+ cascade = Tkinter.Menu(parent)
87+ parent.add_cascade(label=children[0],menu=cascade)
88+ for m in children[1:]: self.add_children(cascade,m)
89+ else:
90+ label,func = children
91+ parent.add_command(label=label,command=func)
92+
diff -r 000000000000 -r 8d3cc8110842 src/PyLAF/framework.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/PyLAF/framework.py Thu Apr 22 14:52:38 2010 +0900
@@ -0,0 +1,323 @@
1+# coding: utf-8
2+
3+import Tkinter, weakref, inspect
4+
5+MASTER, SLAVE = range(2)
6+
7+def iscontain(obj,cls):
8+ try:
9+ bases = inspect.getmro(obj.__class__) # オブジェクトのクラスツリーをタプルで返す
10+ except AttributeError:
11+ return False
12+ if bases.__contains__(cls):
13+ return True
14+ else:
15+ return False
16+
17+def popcnf(key,cnf):
18+ item = None
19+ if cnf.has_key(key):
20+ item = cnf[key]
21+ del cnf[key]
22+ return item
23+
24+class CallableList(list):
25+ '''
26+ 関数を保持するリスト
27+ '''
28+ def call(self):
29+ for func in self:
30+ func()
31+# FuncList = CallableList
32+
33+class SingletonList(list):
34+ '''
35+ 同じアイテムをただひとつしか登録しないリスト
36+ '''
37+ def append(self,obj):
38+ if not self.__contains__(obj):
39+ list.append(self, obj)
40+
41+class WeakRefList(list):
42+ '''
43+ オブジェクトの弱参照を保持するリスト
44+ '''
45+ def contains(self,obj):
46+ return self.tolist().__contains__(obj)
47+ def append(self,obj):
48+ if not self.contains(obj):
49+ list.append(self, weakref.ref(obj))
50+ def insert(self,index,obj):
51+ if not self.contains(obj):
52+ list.insert(self, index, weakref.ref(obj))
53+ def remove(self,obj):
54+ if self.contains(obj):
55+ for ref in self:
56+ if obj is ref():
57+ list.remove(self, ref)
58+ break
59+ def tolist(self):
60+ return [ref() for ref in self]
61+ def cleanup(self):
62+ '''
63+ dead参照のアイテムを削除する
64+ '''
65+ items = []
66+ for ref in self:
67+ if ref() == None:
68+ items.append(ref)
69+ for item in items:
70+ list.remove(self, item)
71+
72+class CallableWeakRefList(WeakRefList):
73+ def call(self):
74+ for o in self: o()()
75+
76+class Listner:
77+ def __init__(self,subject):
78+ self.subject = None
79+ self.register(subject)
80+ def register(self,subject,index=None):
81+ self.unregister()
82+ subject.register(self,index)
83+ self.subject = subject
84+ def unregister(self):
85+ if not self.subject == None:
86+ self.subject.unregister(self)
87+ self.subject = None
88+ def update(self,event): pass
89+
90+class Subject:
91+ def __init__(self):
92+ self.listners = WeakRefList()
93+ def register(self,listner,index=None):
94+ if index == None:
95+ self.listners.append(listner)
96+ else:
97+ self.listners.insert(index,listner)
98+ def unregister(self,listner):
99+ self.listners.cleanup()
100+ self.listners.remove(listner)
101+ def notify(self,*args):
102+ self.listners.cleanup()
103+ for listner in self.listners.tolist(): listner.update(*args)
104+
105+class Port(Listner):
106+ def __init__(self,variable):
107+ Listner.__init__(self,variable)
108+ self._callbacks = CallableList()
109+ def update(self,*args):
110+ self._callbacks.call()
111+ def bind(self,func):
112+ self._callbacks.append(func)
113+ return self
114+ def link(self,*listners):
115+ for listner in listners:
116+ for obj in listner.subject.listners.tolist():
117+ obj.register(self.subject)
118+ return self
119+ def insertlink(self,index,listner):
120+ for obj in listner.subject.listners.tolist():
121+ obj.register(self.subject,index)
122+ return self
123+ def set(self,value,mode=MASTER):
124+ self.subject.set(value,mode)
125+ def get(self):
126+ return self.subject.get()
127+
128+class Variable(Subject):
129+ '''
130+ 複数のPortクラスで同期する任意のリテラルを格納する実体クラス
131+ '''
132+ def __init__(self,value,**kw):
133+ Subject.__init__(self)
134+ self.value = None
135+ self.set(value,mode=SLAVE)
136+ # ==========================
137+ # for backward compatibility
138+ if kw.has_key('value'):
139+ self.set(kw['value'],mode=SLAVE)
140+ del kw['value']
141+ # ==========================
142+ def set(self,value,mode=MASTER):
143+ '''
144+ もしvalueがcopyメソッドを持っていればvalue.copy()する
145+ '''
146+ try:
147+ self.value = value.copy()
148+ except AttributeError:
149+ self.value = value
150+ if mode == MASTER:
151+ self.notify()
152+ else:
153+ self.notify_tk_only()
154+ def notify_tk_only(self,*args):
155+ self.listners.cleanup()
156+ for listner in self.listners.tolist():
157+ if iscontain(listner,VariableTk): listner.update(*args)
158+ def get(self):
159+ '''格納しているオブジェクトの参照を返す'''
160+ return self.value
161+
162+class PortHolder:
163+ '''
164+ Portインスタンスをメンバとして保持する場合に発生する循環参照を自動的に解消する機構
165+ Portインスタンスをメンバとして保持するクラスはPortHolderを継承してdestroyメソッドでパージしなければならない
166+ '''
167+ def _inherit_ports(self,portholder,*ports,**kw):
168+ '''
169+ _inherit_ports(obj)
170+ _inherit_ports(obj,omit=[a,b,c])
171+ _inherit_ports(obj,a,b,c)
172+ '''
173+ m = inspect.getmembers(portholder,lambda x:iscontain(x,Port))
174+ #
175+ omit = []
176+ if kw.has_key('omit'): omit = kw['omit']
177+ #
178+ # print map(lambda x:x[0],m) # リストの第1引数だけをリストアップする
179+ ports = list(ports)
180+ if not ports == []:
181+ m = filter(lambda x:not ports.count(x[0]) == 0,m)
182+ else:
183+ m = filter(lambda x:omit.count(x[0]) == 0,m) # リストの第1引数がomitに含まれないものだけ選択する
184+ for name,info in m: setattr(self, name, getattr(portholder, name))
185+ def destroy(self):
186+ '''メンバからPortインスタンスへの参照を削除する'''
187+ m = inspect.getmembers(self,lambda x:iscontain(x,Port))
188+ for name,info in m: setattr(self, name, None)
189+
190+class ComponentHolder:
191+ '''
192+ Component,FrameComponentインスタンスをメンバとして保持する場合に発生する循環参照を自動的に解消する機構
193+ '''
194+ def _remove(self,m):
195+ for name,info in m:
196+ if not name == 'master':
197+ setattr(self, name, None)
198+ def destroy(self):
199+ '''self.master以外のメンバからComponent,FrameCopmponentインスタンスへの参照を削除する'''
200+ self._remove(inspect.getmembers(self,lambda x:iscontain(x,LeafTk)))
201+ self._remove(inspect.getmembers(self,lambda x:iscontain(x,Tkinter.BaseWidget)))
202+
203+class LeafTk:
204+ '''
205+ Tkinter.BaseWidgetのリーフになれるコンポーネント。Tkinter.pyを参考にした。
206+ '''
207+ def __init__(self,master):
208+ self.master = master
209+ self._name = repr(id(self))
210+ self._assign_to_master()
211+ def _assign_to_master(self):
212+ if self.master.children.has_key(self._name):
213+ '''master.childrenにおけるidの唯一性を保証する'''
214+ self.master.children[self._name].destroy()
215+ self.master.children[self._name] = self
216+ def _remove_from_master(self):
217+ '''master.childrenから自身へのオブジェクト参照を廃棄する'''
218+ if self.master.children.has_key(self._name):
219+ del self.master.children[self._name]
220+ def destroy(self):
221+ self._remove_from_master()
222+
223+class Component(LeafTk,PortHolder,ComponentHolder):
224+ def __init__(self,master):
225+ LeafTk.__init__(self,master)
226+ self.children = {}
227+ def destroy(self):
228+ for c in self.children.values(): c.destroy() # purge children
229+ ComponentHolder.destroy(self) # purge component members
230+ PortHolder.destroy(self) # purge port members
231+ LeafTk.destroy(self) # purge itself
232+ def gui(self,master,cnf={},**kw):
233+ frm = Tkinter.Frame(master,cnf,**kw)
234+ Tkinter.Label(frm,text=self.__class__.__name__).pack(side=Tkinter.TOP,expand=1,fill=Tkinter.X)
235+ return frm
236+ def menu(self,master,cnf={},**kw):
237+ return None
238+
239+class Frame(Tkinter.Frame,PortHolder,ComponentHolder):
240+ def destroy(self):
241+ ComponentHolder.destroy(self)
242+ PortHolder.destroy(self)
243+ Tkinter.Frame.destroy(self)
244+
245+class LabelFrame(Tkinter.LabelFrame,PortHolder,ComponentHolder):
246+ def destroy(self):
247+ ComponentHolder.destroy(self)
248+ PortHolder.destroy(self)
249+ Tkinter.LabelFrame.destroy(self)
250+
251+class Equipment:
252+ def __init__(self,comp,gui=True,guicnf={}):
253+ if inspect.isclass(comp):
254+ self.component = comp(self)
255+ else:
256+ self.component = comp
257+ self._inherit_ports(self.component)
258+ if gui:
259+ self.gui = self.component.gui(self,**guicnf)
260+ self.gui.pack()
261+ def configure(self,gui=None):
262+ if not gui == None:
263+ try:
264+ self.gui.destroy()
265+ except AttributeError: pass
266+ gui(self).pack()
267+
268+class App(Frame,Equipment):
269+ def __init__(self,master,comp,gui=True,menu=True,guicnf={},cnf={},**kw):
270+ Frame.__init__(self,master,cnf,**kw)
271+ Equipment.__init__(self,comp,gui,guicnf)
272+ if menu:
273+ m = self.component.menu(self.master)
274+ if not m == None: self.master.config(menu=m)
275+ def configure(self,gui=None,menu=None,cnf={},**kw):
276+ Frame.configure(self,cnf,**kw)
277+ Equipment.configure(self,gui)
278+ if not menu == None: self.master.config(menu=menu(self.master))
279+
280+class Embed(LabelFrame,Equipment):
281+ def __init__(self,master,comp,gui=True,menu=True,guicnf={},cnf={},**kw):
282+ LabelFrame.__init__(self,master,cnf,**kw)
283+ Equipment.__init__(self,comp,gui,guicnf)
284+ if menu: self.component.menu(self,popup=True)
285+ def configure(self,gui=None,menu=None,cnf={},**kw):
286+ Frame.configure(self,cnf,**kw)
287+ Equipment.configure(self,gui)
288+ if not menu == None: self.master.config(menu=menu(self,popup=True))
289+
290+class VariableTk(Listner):
291+ '''
292+ Variableクラスを参照して同期するよう[Double|Int|String|Boolean]Varを拡張するMixin
293+ '''
294+ def __init__(self,port,forward=lambda x:x,backward=lambda x:x):
295+ Listner.__init__(self,port.subject)
296+ self.forward = forward
297+ self.backward = backward
298+ def update(self,*args):
299+ self.set(self.forward(self.subject.get()))
300+ def fixed(self,*args):
301+ self.subject.set(self.backward(self.get()))
302+ def __eq__(self,other):
303+ return id(self) == id(other)
304+
305+class DoubleVar(Tkinter.DoubleVar,VariableTk):
306+ def __init__(self,port,master=None,value=None,name=None,forward=lambda x:x,backward=lambda x:x):
307+ Tkinter.DoubleVar.__init__(self,master,forward(port.subject.get()),name)
308+ VariableTk.__init__(self,port,forward,backward)
309+
310+class IntVar(Tkinter.IntVar,VariableTk):
311+ def __init__(self,port,master=None,value=None,name=None,forward=lambda x:x,backward=lambda x:x):
312+ Tkinter.IntVar.__init__(self,master,forward(port.subject.get()),name)
313+ VariableTk.__init__(self,port,forward,backward)
314+
315+class StringVar(Tkinter.StringVar,VariableTk):
316+ def __init__(self,port,master=None,value=None,name=None,forward=lambda x:x,backward=lambda x:x):
317+ Tkinter.StringVar.__init__(self,master,forward(port.subject.get()),name)
318+ VariableTk.__init__(self,port,forward,backward)
319+
320+class BooleanVar(Tkinter.BooleanVar,VariableTk):
321+ def __init__(self,port,master=None,value=None,name=None,forward=lambda x:x,backward=lambda x:x):
322+ Tkinter.BooleanVar.__init__(self,master,forward(port.subject.get()),name)
323+ VariableTk.__init__(self,port,forward,backward)
diff -r 000000000000 -r 8d3cc8110842 src/PyLAF/plotters.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/PyLAF/plotters.py Thu Apr 22 14:52:38 2010 +0900
@@ -0,0 +1,271 @@
1+# coding: utf-8
2+
3+import StringIO, Image, ImageTk, matplotlib, tkFileDialog
4+matplotlib.use('Agg')
5+from matplotlib import pyplot
6+from scipy import array, arange, real, imag, sin, pi, fft, log10, fftpack
7+from Tkinter import Label, BOTTOM, Toplevel, mainloop, _cnfmerge
8+from framework import PortHolder, Port, Variable, SLAVE
9+from framework import DoubleVar, IntVar, BooleanVar, StringVar
10+from widgets import popcnf, Menu, GridPane
11+
12+class SimplePlot(Label):
13+ '''
14+ 軽量プロットウィジェット
15+ CanvasTkAgg を使った埋め込みはでは使用後に解放されずメモリに残ってしまうので、
16+ 以下のような軽量プロットを作ってみた。
17+ matplotlib のバックエンドで画像を作成してPILで表示する。
18+ グラフの描画だけなら、むしろこちらの方が管理楽ちん。
19+ インタラクティブにしたい場合は、メインウィンドウと同じライフサイクルでひとつだけCanvasTkAggを使い
20+ 共用するとよいだろう。
21+ '''
22+ def __init__(self,master=None,cnf={},**kw):
23+ if kw: cnf = _cnfmerge((cnf,kw))
24+ figsize, dpi = popcnf('figsize',cnf), popcnf('dpi',cnf)
25+ if figsize == None: figsize = (300,300)
26+ if dpi == None: dpi = 50
27+ Label.__init__(self,master,cnf,**kw)
28+ self.dpi = dpi # dpi は 100 で固定のようだ。なぜか dpi=xxx や set_dpi(xxx) などが反映されない。
29+ size = (float(figsize[0]) / dpi, float(figsize[1]) / dpi)
30+ self.ax = pyplot.figure(figsize=size).add_subplot(111)
31+ def show(self):
32+ imgdata = StringIO.StringIO()
33+ self.ax.figure.savefig(imgdata, format='png')
34+ imgdata.seek(0)
35+ im = Image.open(imgdata)
36+ width, height = self.ax.figure.get_size_inches()
37+ width, height = int(width * self.dpi), int(height * self.dpi)
38+ im = im.resize((width,height),Image.ANTIALIAS) # アンチエイリアス付きで拡大縮小する
39+ self.img = ImageTk.PhotoImage(im) # インスタンスで保持しないと show() を抜けた瞬間に画像が解放されてしまう
40+ self.configure(image=self.img)
41+ def resize(self,figsize=(300,300),dpi=50):
42+ self.dpi = dpi
43+ size = (float(figsize[0]) / dpi, float(figsize[1]) / dpi)
44+ self.ax = pyplot.figure(figsize=size).add_subplot(111)
45+ self.show()
46+ def destroy(self):
47+ Label.destroy(self)
48+ pyplot.close(self.ax.figure)
49+ self.ax = None # AxesSubplot クラスの明示的解放(これしないとゾンビが残る)
50+
51+class BasePlot(SimplePlot,PortHolder):
52+ '''
53+ プロットの基本機能を提供する。オートスケール、書き出し、デコレーションなど。
54+ '''
55+ def destroy(self):
56+ PortHolder.destroy(self)
57+ SimplePlot.destroy(self)
58+ def __init__(self,master=None,cnf={},**kw):
59+ SimplePlot.__init__(self,master,cnf,**kw)
60+ self.sig_in = Port(Variable(value=array([]))).bind(self._sig_in)
61+ self.kwargs = Port(Variable(value={})).bind(self._sig_in)
62+ self.left = Port(Variable(value=0.15)).bind(self._decolation_autoshow)
63+ self.right = Port(Variable(value=0.9)).bind(self._decolation_autoshow)
64+ self.bottom = Port(Variable(value=0.1)).bind(self._decolation_autoshow)
65+ self.title = Port(Variable(value='')).bind(self._decolation_autoshow)
66+ self.xlabel = Port(Variable(value='xlabel')).bind(self._decolation_autoshow)
67+ self.ylabel = Port(Variable(value='ylabel')).bind(self._decolation_autoshow)
68+ xlim = self.ax.get_xlim()
69+ self.xmin = Port(Variable(value=xlim[0])).bind(self._xlim_fixed_autoshow)
70+ self.xmax = Port(Variable(value=xlim[1])).bind(self._xlim_fixed_autoshow)
71+ ylim = self.ax.get_ylim()
72+ self.ymin = Port(Variable(value=ylim[0])).bind(self._ylim_fixed_autoshow)
73+ self.ymax = Port(Variable(value=ylim[1])).bind(self._ylim_fixed_autoshow)
74+ self.autoscalex = Port(Variable(value=True)).bind(self._sig_in)
75+ self.autoscaley = Port(Variable(value=True)).bind(self._sig_in)
76+ self.menu(self,popup=True,tearoff=0)
77+ def configure(self,figsize=None,dpi=None,cnf={},**kw):
78+ if not figsize == None and dpi == None:
79+ self.resize(figsize)
80+ elif not dpi == None and figsize == None:
81+ self.resize(dpi)
82+ elif not figsize == None and not dpi == None:
83+ self.resize(figsize,dpi)
84+ SimplePlot.configure(self,cnf,**kw)
85+ def menu(self,master,cnf={},**kw):
86+ menu = Menu(master,cnf,**kw)
87+ menu.add_command(label="Save Figure",command=self._savefig)
88+ menu.add_command(label="Popup Console",command=self._popup_console)
89+ menu.add_command(label="Popup Decolation",command=self._popup_decoration)
90+ return menu
91+ def gui(self,master,cnf={},**kw):
92+ self.plot(); self.show()
93+ o = self.console(master); o.pack(side=BOTTOM)
94+ return self
95+ def _sig_in(self):
96+ self.plot(self.sig_in.get().transpose()); self.show()
97+ def _popup_decoration(self):
98+ self.decoration(Toplevel(self)).pack()
99+ def _popup_console(self):
100+ self.console(Toplevel(self)).pack()
101+ def _savefig(self):
102+ fname = tkFileDialog.asksaveasfilename(title='Enter Filename')
103+ self.ax.figure.savefig(fname)
104+ def _xlim_fixed_autoshow(self):
105+ self.autoscalex.set(False,mode=SLAVE)
106+ self.ax.set_xlim(self.xmin.get(), self.xmax.get())
107+ self.show()
108+ def _ylim_fixed_autoshow(self):
109+ self.autoscaley.set(False,mode=SLAVE)
110+ self.ax.set_ylim(self.ymin.get(), self.ymax.get())
111+ self.show()
112+ def plot(self,*args,**keys):
113+ self.ax.cla()
114+ self._decolation()
115+ kwargs = self.kwargs.get()
116+ kwargs['scalex'] = self.autoscalex.get()
117+ kwargs['scaley'] = self.autoscaley.get()
118+ self.ax.plot(*args,**kwargs)
119+ self._update_scale()
120+ def replot(self):
121+ self._sig_in()
122+ def _decolation(self):
123+ self.ax.figure.subplots_adjust(left=self.left.get())
124+ self.ax.figure.subplots_adjust(right=self.right.get())
125+ self.ax.figure.subplots_adjust(bottom=self.bottom.get())
126+ self.ax.set_title(self.title.get())
127+ self.ax.set_xlabel(self.xlabel.get())
128+ self.ax.set_ylabel(self.ylabel.get())
129+ def _decolation_autoshow(self):
130+ self._decolation()
131+ self.show()
132+ def _update_scale(self):
133+ xlim = self.ax.get_xlim()
134+ self.xmin.set(xlim[0],mode=SLAVE)
135+ self.xmax.set(xlim[1],mode=SLAVE)
136+ ylim = self.ax.get_ylim()
137+ self.ymin.set(ylim[0],mode=SLAVE)
138+ self.ymax.set(ylim[1],mode=SLAVE)
139+ def console(self,master):
140+ o = GridPane(master)
141+ o.entry_with_tcb('XLIM',BooleanVar(self.autoscalex),DoubleVar(self.xmin),DoubleVar(self.xmax))
142+ o.entry_with_tcb('YLIM',BooleanVar(self.autoscaley),DoubleVar(self.ymin),DoubleVar(self.ymax))
143+ return o
144+ def decoration(self,master):
145+ o = GridPane(master)
146+ o.entry('PADL',DoubleVar(self.left))
147+ o.entry('PADR',DoubleVar(self.right))
148+ o.entry('PADB',DoubleVar(self.bottom))
149+ o.entry('TITLE',StringVar(self.title))
150+ o.entry('XLABEL',StringVar(self.xlabel))
151+ o.entry('YLABEL',StringVar(self.ylabel))
152+ return o
153+
154+class Constellation(BasePlot):
155+ '''
156+ デシメーションなどの機能を多重継承して追加できるといいけどね。
157+ '''
158+ def __init__(self,master=None,cnf={},**kw):
159+ BasePlot.__init__(self,master,cnf,**kw)
160+ self.samplerate = Port(Variable(value=1.)).bind(self._sig_in)
161+ self.style = Port(Variable(value='.')).bind(self._sig_in)
162+ self.alpha = Port(Variable(value=1)).bind(self._sig_in)
163+ self.begin = Port(Variable(value=0.)).bind(self._sig_in) # プロット開始(%)
164+ self.end = Port(Variable(value=100.)).bind(self._sig_in) # プロット終了(%)
165+ self.decimation = Port(Variable(value=1)).bind(self._sig_in)
166+ self.xlabel.set('I Channel [mV]',mode=SLAVE)
167+ self.ylabel.set('Q Channel [mV]',mode=SLAVE)
168+ def _sig_in(self):
169+ sig = self.sig_in.get()
170+ b,e = self.begin.get(), self.end.get()
171+ sig = sig[...,::self.decimation.get()]
172+ sig = sig[...,(b / 100 * sig.shape[-1]):(e / 100 * sig.shape[-1])]
173+ sig = sig.transpose()
174+ kwargs = self.kwargs.get()
175+ kwargs['alpha'] = self.alpha.get()
176+ self.kwargs.set(kwargs,mode=SLAVE)
177+ self.plot(real(sig), imag(sig), self.style.get())
178+ self.show()
179+ self.master.update()
180+ def decoration(self,master):
181+ o = BasePlot.decoration(self,master)
182+ o.entry('Plot Style',StringVar(self.style))
183+ return o
184+ def console(self,master):
185+ o = BasePlot.console(self,master)
186+ o.entry('Sample Rate [MS/sec]',DoubleVar(self.samplerate))
187+ o.entry('Alpha Index',DoubleVar(self.alpha))
188+ o.entry('Decimation Index',IntVar(self.decimation))
189+ return o
190+
191+class XYPlot(BasePlot):
192+ def __init__(self,master=None,cnf={},**kw):
193+ BasePlot.__init__(self,master,cnf,**kw)
194+ self.xaxis = Port(Variable(value=array([]))).bind(self._sig_in)
195+ self.yaxis = Port(Variable(value=array([]))).bind(self._sig_in)
196+ self.style = Port(Variable(value='-')).bind(self._sig_in)
197+ self.xlabel.set('X Axis',mode=SLAVE)
198+ self.ylabel.set('Y Axis',mode=SLAVE)
199+ def _sig_in(self):
200+ xaxis, yaxis = self.xaxis.get(), self.yaxis.get()
201+ if xaxis.shape[-1] == yaxis.shape[-1]:
202+ self.plot(xaxis, yaxis.transpose(), self.style.get())
203+ self.show()
204+
205+class Oscilloscope(BasePlot):
206+ def __init__(self,master=None,cnf={},**kw):
207+ BasePlot.__init__(self,master,cnf,**kw)
208+ self.samplerate = Port(Variable(value=1.)).bind(self._sig_in)
209+ self.decimation = Port(Variable(value=1)).bind(self._sig_in)
210+ self.style = Port(Variable(value='-')).bind(self._sig_in)
211+ self.xlabel.set('Time [us]',mode=SLAVE)
212+ self.ylabel.set('Signal [mV]',mode=SLAVE)
213+ def _sig_in(self):
214+ sig = self.sig_in.get()
215+ sig = sig[...,::self.decimation.get()]
216+ samplerate = self.samplerate.get() / self.decimation.get()
217+ time = 1. / samplerate * arange(sig.shape[-1])
218+ self.plot(time, sig.transpose(), self.style.get())
219+ self.show()
220+ def console(self,master):
221+ o = BasePlot.console(self,master)
222+ o.entry('Sample Rate [MS/sec]',DoubleVar(self.samplerate))
223+ o.entry('Decimation Index',IntVar(self.decimation))
224+ return o
225+
226+class Spectrum(BasePlot):
227+ def __init__(self,master=None,cnf={},**kw):
228+ BasePlot.__init__(self,master,cnf,**kw)
229+ self.samplerate = Port(Variable(value=1.)).bind(self._sig_in)
230+ self.style = Port(Variable(value='-')).bind(self._sig_in)
231+ self.decimation = Port(Variable(value=1)).bind(self._sig_in)
232+ self.xlabel.set('Frequency [MHz]',mode=SLAVE)
233+ self.ylabel.set('Power [dBm]',mode=SLAVE)
234+ def _sig_in(self):
235+ sig = self.sig_in.get()
236+ samplerate = self.samplerate.get() / self.decimation.get()
237+ style = self.style.get()
238+ sig = sig[...,::self.decimation.get()]
239+ # sig = sig[:2**int(log2(sig.size))]
240+ f = fft(sig)
241+ # f[0] = f[0] * .5 # 片側スペクトルを見たい場合にはこの行をアクティベート
242+ v = fftpack.fftshift(f * 2.0 / sig.size)
243+ freq = fftpack.fftshift(fftpack.fftfreq(sig.size,1./samplerate))
244+ value = 10 * log10(real(v*v.conj())/2/50) - 30
245+ self.plot(freq, value, style)
246+ self.show()
247+ self.master.update()
248+ def console(self,master):
249+ o = BasePlot.console(self,master)
250+ o.entry('Sample Rate [MS/sec]',DoubleVar(self.samplerate))
251+ o.entry('Decimation Index',IntVar(self.decimation))
252+ return o
253+
254+def test(master=None):
255+ from framework import App
256+ o = App(master,Spectrum); o.pack()
257+ osc = App(Toplevel(master),Oscilloscope); osc.pack()
258+ o.sig_in.link(osc.sig_in)
259+ o.samplerate.link(osc.samplerate)
260+ o.samplerate.set(250.,mode=SLAVE)
261+ osc.xmin.set(0)
262+ osc.xmax.set(1000)
263+ d = 1. / o.samplerate.get()
264+ t = arange(1e+6) * d # [us]
265+ y = 1000. * sin(2 * pi * 9.12 * t) # 10Vpp -> 30dBm 1Vpp -> 10dBm
266+ y = y + 787.3 * (sin(2 * pi * 10 * t) > 0.) # [mV]
267+ o.sig_in.set(y)
268+
269+if __name__ == '__main__':
270+ test()
271+ mainloop()
diff -r 000000000000 -r 8d3cc8110842 src/PyLAF/widgets.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/PyLAF/widgets.py Thu Apr 22 14:52:38 2010 +0900
@@ -0,0 +1,138 @@
1+# coding: utf-8
2+
3+import Tkinter
4+
5+def popcnf(key,cnf):
6+ item = None
7+ if cnf.has_key(key):
8+ item = cnf[key]
9+ del cnf[key]
10+ return item
11+
12+def root(title='tk'):
13+ root = Tkinter.Tk()
14+ root.title(title)
15+ return root
16+
17+def toplevel(master=None,title='tk',cnf={},**kw):
18+ if kw: cnf = Tkinter._cnfmerge((cnf,kw))
19+ top = Tkinter.Toplevel(master,cnf)
20+ top.title(title)
21+ return top
22+
23+def popup_button(master,command,label='',title='tk',cnf={},**kw):
24+ if kw: cnf = Tkinter._cnfmerge((cnf,kw))
25+ popup = lambda: command(toplevel(master,title,cnf)).pack()
26+ return Tkinter.Button(master,text=label,command=popup)
27+
28+class Entry(Tkinter.Entry):
29+ def __init__(self,master=None,cnf={},**kw):
30+ if kw: cnf = Tkinter._cnfmerge((cnf,kw))
31+ if cnf.has_key('textvariable'):
32+ v = cnf['textvariable']
33+ del cnf['textvariable']
34+ Tkinter.Entry.__init__(self,master,cnf)
35+ self.config(textvariable=v)
36+ self.bind('<Return>',v.fixed)
37+ self.bind('<Leave>',v.update)
38+ else:
39+ Tkinter.Entry.__init__(self,master,cnf)
40+
41+class Menu(Tkinter.Menu):
42+ def __init__(self,master=None,cnf={},**kw):
43+ if kw: cnf = Tkinter._cnfmerge((cnf,kw))
44+ popup = popcnf('popup',cnf)
45+ Tkinter.Menu.__init__(self,master,cnf)
46+ self.cbname_ctrl_b1 = None
47+ self.cbname_b3 = None
48+ if popup:
49+ self.cbname_ctrl_b1 = master.bind("<Control-Button-1>", self._rclicked)
50+ self.cbname_b3 = master.bind(self._right_button(), self._rclicked)
51+ def _rclicked(self,e):
52+ self.tk_popup(e.x_root, e.y_root)
53+ def _right_button(self):
54+ import platform
55+ if platform.system() == 'Darwin':
56+ rbtn = '<Button-2>'
57+ else:
58+ rbtn = '<Button-3>'
59+ return rbtn
60+ def destroy(self):
61+ if not self.cbname_ctrl_b1 == None:
62+ self.master.unbind('<Control-Button-1>',self.cbname_ctrl_b1)
63+ if not self.cbname_b3 == None:
64+ self.master.unbind(self._right_button(),self.cbname_b3)
65+ Tkinter.Menu.destroy(self)
66+
67+class TriggerButton(Tkinter.Button):
68+ def __init__(self,master=None,cnf={},**kw):
69+ if kw: cnf = Tkinter._cnfmerge((cnf,kw))
70+ if cnf.has_key('variable'):
71+ v = cnf['variable']
72+ del cnf['variable']
73+ Tkinter.Button.__init__(self,master,cnf)
74+ self.config(command=v.fixed)
75+ else:
76+ Tkinter.Button.__init__(self,master,cnf)
77+
78+class PopupButton(Tkinter.Button):
79+ def __init__(self,master=None,command=None,label='',title='tk',cnf={},**kw):
80+ if kw: cnf = Tkinter._cnfmerge((cnf,kw))
81+ popup = lambda: command(toplevel(master,title)).pack()
82+ Tkinter.Button.__init__(self,master,cnf)
83+ self.config(text=label,command=popup)
84+
85+class TriggerCheckbutton(Tkinter.Checkbutton):
86+ def __init__(self,master=None,cnf={},**kw):
87+ if kw: cnf = Tkinter._cnfmerge((cnf,kw))
88+ if cnf.has_key('variable'):
89+ Tkinter.Checkbutton.__init__(self,master,cnf)
90+ self.config(command=cnf['variable'].fixed)
91+ else:
92+ Tkinter.Checkbutton.__init__(self,master,cnf)
93+
94+# Checkbuttonは必ずしも決まったトリガの使い方ではないのでオーバーライドしない。
95+# Checkbutton(master,variable=comp.port.variable)
96+
97+class GridPane(Tkinter.Frame):
98+ def entry(self,label='',*variables):
99+ widgets = [Entry(self,textvariable=v) for v in variables]
100+ self.append(label,*widgets)
101+ def trigger(self,label='',*variables):
102+ widgets = [TriggerButton(self,text=label,variable=v) for v in variables]
103+ row = self.grid_size()[1]
104+ for i,w in enumerate(widgets): w.grid(row=row,column=i+1,sticky='EW')
105+ def popup(self,label='',command=None,title='tk',cnf={},**kw):
106+ if kw: cnf = Tkinter._cnfmerge((cnf,kw))
107+ popup = lambda: command(toplevel(self.master,title,cnf)).pack()
108+ widget = Tkinter.Button(self,text='console',command=popup)
109+ self.append(label,widget)
110+ def entry_with_tcb(self,label,booleanvar,*variables):
111+ row = self.grid_size()[1]
112+ frm = Tkinter.Frame(self)
113+ TriggerCheckbutton(frm,variable=booleanvar).pack(side=Tkinter.LEFT)
114+ Tkinter.Label(frm,text=label).pack(side=Tkinter.LEFT)
115+ frm.grid(row=row,column=0)
116+ widgets = [Entry(self,textvariable=v) for v in variables]
117+ for i,w in enumerate(widgets): w.grid(row=row,column=i+1)
118+ def triggered_checkbutton(self,label,booleanvar):
119+ row = self.grid_size()[1]
120+ TriggerCheckbutton(self,variable=booleanvar,text=label).grid(row=row,column=0)
121+# Tkinter.Label(self,text=label).grid(row=row,column=1)
122+ def append(self,label='',*widgets):
123+ row = self.grid_size()[1]
124+ Tkinter.Label(self,text=label).grid(row=row,column=0)
125+ for i,w in enumerate(widgets): w.grid(row=row,column=i+1)
126+ #
127+ def wappend(self,*widgets):
128+ row = self.grid_size()[1]
129+ for i,w in enumerate(widgets): w.grid(row=row,column=i)
130+ def wtrigger(self,*labelvariables):
131+ return [TriggerButton(self,text=l,variable=v) for l,v in labelvariables]
132+
133+class Projection:
134+ @classmethod
135+ def db(cls):
136+ from scipy import log10
137+ return {'forward' : lambda x: 10*log10(x),
138+ 'backward' : lambda x: 10**(x/10.)}
diff -r 000000000000 -r 8d3cc8110842 src/examples/FGSIN.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/examples/FGSIN.py Thu Apr 22 14:52:38 2010 +0900
@@ -0,0 +1,42 @@
1+# coding: utf-8
2+import Tkinter
3+# PyLAFをロードするとTkinterが暗黙でインポートされるが、
4+# Pythonに不慣れなユーザが混乱しないよう、わかりやすさの為にTkinterを明示的にインポートした
5+from PyLAF import *
6+from scipy import savetxt
7+
8+class FGSIN(EasyComponent):
9+ PLOTTER = Oscilloscope
10+ def __init__(self,master=None):
11+ EasyComponent.__init__(self,master)
12+ self.mag = EasyPort(Variable(1.),'Magnitude [mV]').bind(self.trigger)
13+ self.freq = EasyPort(Variable(0.01),'Frequency [MHz]').bind(self.trigger)
14+ self.phase = EasyPort(Variable(0.),'Phase Offset [deg]').bind(self.trigger)
15+ self.bias = EasyPort(Variable(0.),'Bias Voltage [mV]').bind(self.trigger)
16+ self.dt = EasyPort(Variable(1.),'Time Step [us]').bind(self.trigger)
17+ self.tend = EasyPort(Variable(500.),'End [us]').bind(self.trigger)
18+ self._menu = [['File', ['Load', None],
19+ ['Save', ['All', None],
20+ ['As' , self.save]]],
21+ ['Edit', ['Copy' , None],
22+ ['Cut' , None],
23+ ['Paste', None]]
24+ ]
25+ def trigger(self):
26+ t = arange(0.,self.tend.get(),self.dt.get())
27+ self.sig_out.set(self.mag.get() * sin(2 * pi * self.freq.get() * t + self.phase.get() / 180. * pi) + self.bias.get())
28+ def save(self):
29+ fname = tkFileDialog.asksaveasfilename(title='Save As?')
30+ if fname != "":
31+ file = open(fname,'w')
32+ savetxt(file,self.sig_out.get().transpose(),delimiter=',')
33+ file.close()
34+
35+def test(master=None):
36+ o = App(master,FGSIN)
37+ o.master.title('FGSIN'); o.pack()
38+ o.component.trigger()
39+
40+if __name__ == '__main__':
41+ test(Tkinter.Tk())
42+ Tkinter.mainloop()
diff -r 000000000000 -r 8d3cc8110842 src/examples/MIXER.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/examples/MIXER.py Thu Apr 22 14:52:38 2010 +0900
@@ -0,0 +1,37 @@
1+# coding: utf-8
2+import Tkinter
3+from scipy import array
4+from PyLAF import EasyComponent, Embed, Port, Variable, Oscilloscope, Spectrum
5+from FGSIN import FGSIN
6+
7+class MIXER(EasyComponent):
8+ PLOTTER = Oscilloscope
9+ def __init__(self,master=None):
10+ EasyComponent.__init__(self,master)
11+ self.sig_a = Port(Variable(array([]))).bind(self.trigger)
12+ self.sig_b = Port(Variable(array([]))).bind(self.trigger)
13+ def trigger(self):
14+ a, b = self.sig_a.get(), self.sig_b.get()
15+ if a.shape == b.shape:
16+ self.sig_out.set(self.sig_a.get() * self.sig_b.get())
17+
18+def test_embed(master=None):
19+ master.title('MODULATION:AM')
20+ frm = Tkinter.Frame(master); frm.pack(side=Tkinter.RIGHT)
21+ mx = Embed(frm,MIXER,text='MIXER:RF'); mx.pack(side=Tkinter.TOP)
22+ vw = Embed(frm,Spectrum,text='FGSIN:IF'); vw.pack(side=Tkinter.TOP)
23+ lo = Embed(master,FGSIN,text='FGSIN:LO'); lo.pack(side=Tkinter.RIGHT)
24+ im = Embed(master,FGSIN,text='FGSIN:IF'); im.pack(side=Tkinter.RIGHT)
25+ vw.xmin.set(0.); vw.xmax.set(.2)
26+ lo.freq.set(0.1)
27+ im.bias.set(1.0)
28+ lo.dt.link(im.dt)
29+ lo.tend.link(im.tend)
30+ lo.sig_out.link(mx.sig_a)
31+ im.sig_out.link(mx.sig_b)
32+ mx.sig_out.link(vw.sig_in)
33+ lo.component.trigger()
34+
35+if __name__ == '__main__':
36+ test_embed(Tkinter.Tk())
37+ Tkinter.mainloop()
diff -r 000000000000 -r 8d3cc8110842 src/examples/MODAM.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/examples/MODAM.py Thu Apr 22 14:52:38 2010 +0900
@@ -0,0 +1,39 @@
1+# coding: utf-8
2+from PyLAF import *
3+from MIXER import MIXER
4+from FGSIN import FGSIN
5+
6+class MODAM(Component):
7+ def __init__(self,master=None):
8+ Component.__init__(self,master)
9+ self.fglo = fglo = FGSIN(self)
10+ self.fgif = fgif = FGSIN(self)
11+ self.mixer = mixer = MIXER(self)
12+ fglo.dt.link(fgif.dt)
13+ fglo.tend.link(fgif.tend)
14+ fglo.sig_out.link(mixer.sig_a)
15+ fgif.sig_out.link(mixer.sig_b)
16+ fgif.bias.set(1.0)
17+ fglo.freq.set(0.1)
18+ def gui(self,master,cnf={},**kw):
19+ frm = Frame(master)
20+ out = Tkinter.Frame(frm); out.pack(side=Tkinter.RIGHT)
21+ setattr(frm,'mixer',Embed(out,self.mixer,text='MIXER:RF')); frm.mixer.pack(side=Tkinter.TOP)
22+ setattr(frm,'spana',Embed(out,Spectrum,text='Spectrum:RF')); frm.spana.pack(side=Tkinter.TOP)
23+ setattr(frm,'fglo' ,Embed(frm,self.fglo,text='FGSIN:LO')); frm.fglo.pack(side=Tkinter.RIGHT)
24+ setattr(frm,'fgif' ,Embed(frm,self.fgif,text='FGSIN:IF')); frm.fgif.pack(side=Tkinter.RIGHT)
25+ self.mixer.sig_out.link(frm.spana.sig_in)
26+ self.fglo.trigger()
27+ self.fgif.trigger()
28+ return frm
29+
30+def test(master=None):
31+ master.title('MODULATION:AM')
32+ master.option_add('*font','FixedSys 10')
33+ o = App(master,MODAM); o.pack()
34+ o.gui.spana.gui.resize((200,200)) # o.gui.spana.gui.configure(figsize=(200,200))でもいい
35+ o.component.mixer.trigger()
36+
37+if __name__ == '__main__':
38+ test(Tkinter.Tk())
39+ Tkinter.mainloop()
diff -r 000000000000 -r 8d3cc8110842 src/examples/MODAMdualgui.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/examples/MODAMdualgui.py Thu Apr 22 14:52:38 2010 +0900
@@ -0,0 +1,53 @@
1+# coding: utf-8
2+from PyLAF import *
3+from MIXER import MIXER
4+from FGSIN import FGSIN
5+from functools import partial
6+
7+class MODAM(Component):
8+ def __init__(self,master=None):
9+ Component.__init__(self,master)
10+ self.fglo = fglo = FGSIN(self)
11+ self.fgif = fgif = FGSIN(self)
12+ self.mixer = mixer = MIXER(self)
13+ fglo.dt.link(fgif.dt)
14+ fglo.tend.link(fgif.tend)
15+ fglo.sig_out.link(mixer.sig_a)
16+ fgif.sig_out.link(mixer.sig_b)
17+ fgif.bias.set(1.0)
18+ fglo.freq.set(0.1)
19+ self._menu = [['Sub', ['FGLO', partial(self.popup,master=master,comp=self.fglo)],
20+ ['SPANA', partial(self.popup_spana,master=master)]]]
21+ def gui(self,master,cnf={},**kw):
22+ frm = Frame(master)
23+ setattr(frm,'mixer',Embed(frm,self.mixer,text='MIXER:RF')); frm.mixer.pack(side=Tkinter.RIGHT)
24+ setattr(frm,'fgif' ,Embed(frm,self.fgif,text='FGSIN:IF')); frm.fgif.pack(side=Tkinter.RIGHT)
25+ self.fgif.trigger()
26+ return frm
27+ def guib(self,master,cnf={},**kw):
28+ frm = Frame(master)
29+ setattr(frm,'mixer',Embed(frm,self.mixer,text='MIXER:RF')); frm.mixer.pack(side=Tkinter.RIGHT)
30+ setattr(frm,'fgif' ,Embed(frm,self.fgif,text='FGSIN:IF')); frm.fgif.pack(side=Tkinter.RIGHT)
31+ setattr(frm,'fglo' ,Embed(frm,self.fglo,text='FGSIN:LO')); frm.fglo.pack(side=Tkinter.RIGHT)
32+ self.fgif.trigger()
33+ self.fglo.trigger()
34+ return frm
35+ def menu(self,master,cnf={},**kw):
36+ menu = EasyMenu(master,list=self._menu,cnf=cnf,**kw)
37+ return menu
38+ def popup(self,master,comp):
39+ App(Tkinter.Toplevel(master),comp).pack()
40+ comp.trigger()
41+ def popup_spana(self,master):
42+ o = App(Tkinter.Toplevel(master),Spectrum); o.pack()
43+ self.mixer.sig_out.link(o.component.sig_in)
44+ self.mixer.sig_out.set(self.mixer.sig_out.get())
45+
46+def test(master=None):
47+ master.title('MODULATION:AM')
48+ o = App(master,MODAM,gui=False); o.pack()
49+ o.configure(gui=o.component.guib)
50+
51+if __name__ == '__main__':
52+ test(Tkinter.Tk())
53+ Tkinter.mainloop()
diff -r 000000000000 -r 8d3cc8110842 src/examples/MODAMpopup.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/examples/MODAMpopup.py Thu Apr 22 14:52:38 2010 +0900
@@ -0,0 +1,44 @@
1+# coding: utf-8
2+from PyLAF import *
3+from MIXER import MIXER
4+from FGSIN import FGSIN
5+from functools import partial
6+
7+class MODAM(Component):
8+ def __init__(self,master=None):
9+ Component.__init__(self,master)
10+ self.fglo = fglo = FGSIN(self)
11+ self.fgif = fgif = FGSIN(self)
12+ self.mixer = mixer = MIXER(self)
13+ fglo.dt.link(fgif.dt)
14+ fglo.tend.link(fgif.tend)
15+ fglo.sig_out.link(mixer.sig_a)
16+ fgif.sig_out.link(mixer.sig_b)
17+ fgif.bias.set(1.0)
18+ fglo.freq.set(0.1)
19+ self._menu = [['Sub', ['FGLO', partial(self.popup,master=master,comp=self.fglo)],
20+ ['SPANA', partial(self.popup_spana,master=master)]]]
21+ def gui(self,master,cnf={},**kw):
22+ frm = Frame(master)
23+ setattr(frm,'mixer',Embed(frm,self.mixer,text='MIXER:RF')); frm.mixer.pack(side=Tkinter.RIGHT)
24+ setattr(frm,'fgif' ,Embed(frm,self.fgif,text='FGSIN:IF')); frm.fgif.pack(side=Tkinter.RIGHT)
25+ self.fgif.trigger()
26+ return frm
27+ def menu(self,master,cnf={},**kw):
28+ menu = EasyMenu(master,list=self._menu,cnf=cnf,**kw)
29+ return menu
30+ def popup(self,master,comp):
31+ App(Tkinter.Toplevel(master),comp).pack()
32+ comp.trigger()
33+ def popup_spana(self,master):
34+ o = App(Tkinter.Toplevel(master),Spectrum); o.pack()
35+ self.mixer.sig_out.link(o.component.sig_in)
36+ self.mixer.sig_out.set(self.mixer.sig_out.get())
37+
38+def test(master=None):
39+ master.title('MODULATION:AM')
40+ o = App(master,MODAM); o.pack()
41+
42+if __name__ == '__main__':
43+ test(Tkinter.Tk())
44+ Tkinter.mainloop()
diff -r 000000000000 -r 8d3cc8110842 src/examples/modam_set1.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/examples/modam_set1.py Thu Apr 22 14:52:38 2010 +0900
@@ -0,0 +1,20 @@
1+# coding: utf-8
2+import Tkinter
3+from PyLAF import App
4+from FGSIN import FGSIN
5+from MIXER import MIXER
6+
7+master = Tkinter.Tk()
8+
9+mx = App(master,MIXER); mx.master.title('MIXER:RF'); mx.pack()
10+lo = App(Tkinter.Toplevel(master),FGSIN); lo.master.title('FGSIN:LO'); lo.pack()
11+im = App(Tkinter.Toplevel(master),FGSIN); im.master.title('FGSIN:IF'); im.pack()
12+lo.freq.set(0.1)
13+im.bias.set(1.0)
14+lo.sig_out.link(mx.sig_a)
15+im.sig_out.link(mx.sig_b)
16+lo.dt.link(im.dt)
17+lo.tend.link(im.tend)
18+mx.component.trigger()
19+
20+Tkinter.mainloop()
diff -r 000000000000 -r 8d3cc8110842 src/examples/modam_set2.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/examples/modam_set2.py Thu Apr 22 14:52:38 2010 +0900
@@ -0,0 +1,21 @@
1+# coding: utf-8
2+import Tkinter
3+from PyLAF import Embed
4+from FGSIN import FGSIN
5+from MIXER import MIXER
6+
7+master = Tkinter.Tk()
8+master.title('MODULATION:AM')
9+
10+mx = Embed(master,MIXER,text='MIXER:RF'); mx.pack(side=Tkinter.RIGHT)
11+lo = Embed(master,FGSIN,text='FGSIN:LO'); lo.pack(side=Tkinter.RIGHT)
12+im = Embed(master,FGSIN,text='FGSIN:IF'); im.pack(side=Tkinter.RIGHT)
13+im.bias.set(1.0)
14+lo.freq.set(0.1)
15+lo.dt.link(im.dt)
16+lo.tend.link(im.tend)
17+lo.sig_out.link(mx.sig_a)
18+im.sig_out.link(mx.sig_b)
19+mx.component.trigger()
20+
21+Tkinter.mainloop()
diff -r 000000000000 -r 8d3cc8110842 src/examples/modam_set3.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/examples/modam_set3.py Thu Apr 22 14:52:38 2010 +0900
@@ -0,0 +1,25 @@
1+# coding: utf-8
2+import Tkinter
3+from PyLAF import Embed, App, Spectrum
4+from FGSIN import FGSIN
5+from MIXER import MIXER
6+
7+master = Tkinter.Tk()
8+master.title('MODULATION:AM')
9+
10+frm = Tkinter.Frame(master); frm.pack(side=Tkinter.RIGHT)
11+mx = Embed(frm,MIXER,text='MIXER:RF'); mx.pack(side=Tkinter.TOP)
12+lo = Embed(master,FGSIN,text='FGSIN:LO'); lo.pack(side=Tkinter.RIGHT)
13+im = Embed(master,FGSIN,text='FGSIN:IF'); im.pack(side=Tkinter.RIGHT)
14+im.bias.set(1.0)
15+lo.freq.set(0.1)
16+lo.dt.link(im.dt)
17+lo.tend.link(im.tend)
18+lo.sig_out.link(mx.sig_a)
19+im.sig_out.link(mx.sig_b)
20+
21+vw = App(Tkinter.Toplevel(master),Spectrum); vw.master.title('Spectrum:RF'); vw.pack(side=Tkinter.TOP)
22+mx.sig_out.link(vw.sig_in)
23+mx.component.trigger()
24+
25+Tkinter.mainloop()
Show on old repository browser