亲手翻译,欢迎转载。动态修订,请附原址:http://my.oschina.net/u/2306127/admin/edit-blog?blog=596025
关于Orange Widgets的开发完整教程参见:http://orange-development.readthedocs.org/
创建一个完整的Widgets
在创建了一个简单的widgets帮助了解了基本概念之后,我们来制作一个真正有用的widgets,可以安装到系统与其它的widgets一起协同工作。
我们先从简单的开始,在input中接收data set然后output输出10%的数据实例。将其命名为OWDataSamplerA。
创建一个包“Demo”
首先,为了在Orange Canvas的toolbox显示,我们创建 python project 名字为:orange-demo
工程文件目录如下:
orange-demo/
setup.py
orangedemo/
__init__.py
OWDataSamplerA.py
这个 orange-demo/setup.py
文件包括:
from setuptools import setup
setup(name="Demo",
packages=["orangedemo"],
package_data={"orangedemo": ["icons/*.svg"]},
classifiers=["Example :: Invalid"],
# Declare orangedemo package to contain widgets for the "Demo" category
entry_points={"orange.widgets": ("Demo = orangedemo")},
)
注意,我们申明了一个orangedemo软件包,包含了的widgets放在Demo这一个类目中。
参考:https://github.com/biolab/orange3/wiki/Add-Ons
创建数据处理Widget
与前面的教程(快速入门)类似,新定义的模块OWDataSamplerA所包含的widget如下:
import sys
import numpy
import Orange.data
from Orange.widgets import widget, gui
class OWDataSamplerA(widget.OWWidget):
name = "Data Sampler"
description = "Randomly selects a subset of instances from the data set"
icon = "icons/DataSamplerA.svg"
priority = 10
inputs = [("Data", Orange.data.Table, "set_data")]
outputs = [("Sampled Data", Orange.data.Table)]
want_main_area = False
def __init__(self):
super().__init__()
# GUI
box = gui.widgetBox(self.controlArea, "Info")
self.infoa = gui.widgetLabel(box, 'No data on input yet, waiting to get something.')
self.infob = gui.widgetLabel(box, '')
Widget 定义了一个input和一个output通道。对于input,是Data通道l,接受的对象类型为Orange.data.Table,指定了
set_data()
方法来进行处理。我们使用 output通道,命名为“Sampled Data”,也是同样的对象类型(Orange.data.Table
).
可能你已经注意到了,channels的类型是通过class来指定的,可以使用任何类。但如果希望widgets能跟别的widgets通讯的话,需要使用那些通用的类,如果不一样的话,就要避免已经使用的名称重复。幸运的是,作为一个主要的设计原则,只有很少的channel类型在目前的Orange widgets中使用。
我们的widget不显示任何东西,我们放置两个labels在控件区域围绕一个“Info”区域。
下面的四行指定了widgets的GUI。非常简单,仅仅包含两行文本,如果没有什么发生第一行将报告“no data yet”,第二行是空的状态。
定义数据处理方法
为了完成这个widget,我们现在需要定义如何处理输入数据。这个工作放在set_data()
方法中(上面在介绍input channel时,我们提到了这个方法的定义。)
def set_data(self, dataset):
if dataset is not None:
self.infoa.setText('%d instances in input data set' % len(dataset))
indices = numpy.random.permutation(len(dataset))
indices = indices[:int(numpy.ceil(len(dataset) * 0.1))]
sample = dataset[indices]
self.infob.setText('%d sampled instances' % len(sample))
self.send("Sampled Data", sample)
else:
self.infoa.setText('No data on input yet, waiting to get something.')
self.infob.setText('')
self.send("Sampled Data", None)
这个 dataset
参数就是通过input channel传送过来的token。
对非空的token进行处理,widget在收到数据时更新界面,然后进行数据抽样data sampling更新界面,报告抽样的实例。最后,抽完样的数据被送往output channel,名称为“Sampled Data”。
设置icon
尽管我们的widget已经准备好了测试,为了最后的感觉,我们为其设计一个图标。图标文件在widget header中指定,我们命名为DataSamplerA.svg
,然后放在icons子目录下,位于orangedemo目录中。
安装widget软件包
现在我们安装 orangedemo 软件包。运行 pip install -e .
命令,在orange-demo目录下,按照缺省的安装,需要预先激活Orange的VirtualEnv环境,执行:
source orange3env/bin/activate
注意:安装时可能需要 administrator/superuser 权限,根据python的安装环境有关。
测试widget
为了测试,我们把这个widget放到 Orange Canvas中,将会出现一个新的widget toolbox 叫做 Demo。点击这个面板,将显示数据抽样器的图标。鼠标在上面晃动时可以看到更详细的提示信息:
现在开始实际的测试,放置一个File widget ,然后载入iris.tab 数据集。再放上Data Sampler widget,然后双击打开窗口:
创建一个数据输入Channel
现在连接文件和抽样器,从文件右侧点按鼠标拉到抽样器图标的左侧,释放鼠标就可以看到连接被建立起来。 token等待输入,然后从文件widget发送到Data Sampler widget,,然后更新窗口:
要看一下抽样器确实发送了数据到output通道,再添加和连接一个Data Table widget,如下所示:
试着打开另外一个数据文件,改变将会通过Widget扩散,当数据表窗口打开时,能够立即看到抽样的结果。试着移去文件和抽样器之间的连接(右键点击连接),看看数据表将发生什么情况?
独立运行这个Widget
作为一个通用的规则,每一个widget都有一个 main 启动函数,这样可以在Orange Canvas之外独立地运行。
将下面的代码复制到到DataSampleDemo.py中,然后在Orange的VirtualEnv的环境下运行。
def main(argv=sys.argv):
from PyQt4.QtGui import QApplication
app = QApplication(list(argv))
args = app.argv()
if len(argv) > 1:
filename = argv[1]
else:
filename = "iris"
ow = OWDataSamplerA()
ow.show()
ow.raise_()
dataset = Orange.data.Table(filename)
ow.set_data(dataset)
ow.handleNewSignals()
app.exec_()
ow.set_data(None)
ow.handleNewSignals()
return 0
if __name__=="__main__":
sys.exit(main())
来源:oschina
链接:https://my.oschina.net/u/2306127/blog/596025