Orange的扩展插件Widgets开发(二)-制作流程

感情迁移 提交于 2020-04-06 22:38:59

亲手翻译,欢迎转载。动态修订,请附原址: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。点击这个面板,将显示数据抽样器的图标。鼠标在上面晃动时可以看到更详细的提示信息:

_images/samplewidgetontoolbox.png

现在开始实际的测试,放置一个File widget ,然后载入iris.tab 数据集。再放上Data Sampler widget,然后双击打开窗口:

_images/datasamplerAempty.png

创建一个数据输入Channel

现在连接文件和抽样器,从文件右侧点按鼠标拉到抽样器图标的左侧,释放鼠标就可以看到连接被建立起来。 token等待输入,然后从文件widget发送到Data Sampler widget,,然后更新窗口:

_images/datasamplerAupdated.png

要看一下抽样器确实发送了数据到output通道,再添加和连接一个Data Table widget,如下所示:

_images/schemawithdatatable.png

试着打开另外一个数据文件,改变将会通过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())



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!