Orange的擴展插件Widgets開發(二)-製做流程

親手翻譯,歡迎轉載。動態修訂,請附原址:http://my.oschina.net/u/2306127/admin/edit-blog?blog=596025python

關於Orange Widgets的開發完整教程參見:http://orange-development.readthedocs.org/git


建立一個完整的Widgets

在建立了一個簡單的widgets幫助瞭解了基本概念以後,咱們來製做一個真正有用的widgets,能夠安裝到系統與其它的widgets一塊兒協同工做。github

咱們先從簡單的開始,在input中接收data set而後output輸出10%的數據實例。將其命名爲OWDataSamplerAshell

建立一個包「Demo」

首先,爲了在Orange Canvas的toolbox顯示,咱們建立 python project 名字爲:orange-demoapp

工程文件目錄以下:dom

orange-demo/
      setup.py
      orangedemo/
                  __init__.py
                  OWDataSamplerA.py

這個 orange-demo/setup.py 文件包括:svg

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以下:ui

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())
相關文章
相關標籤/搜索