抽象&复杂IPython小组件仪表板的设计模式

时间:2017-12-01 10:04:55

标签: ipython jupyter ipywidgets

IPywidgets手册在很大程度上非常有用,但缺乏关于如何创建复杂仪表板的一些解释。特别是,我想知道如何:

  1. 设计抽象,以帮助构建易于扩展的仪表板,其中包含多个相互依赖的小部件,其中一些小部件隐藏/显示其他小部件。
  2. 以允许我获取所有小部件的状态设置为dict的方式执行此操作,以便随后我可以实现按钮保存仪表板的配置并将其加载到JSON文件。
  3. 为了使这个问题更加具体,我设计了一个当前方法的最小例子,该例子基于a design pattern我在@ Jupyter Widgets channel on Gitter上从@jasongrout收到的;在回答时,请通过重新实现此示例来证明您的设计模式,确保明确满足上述两个标准:

    from IPython.display import display
    import IPython.display as ipd
    import ipywidgets as widgets
    import matplotlib.pyplot as plt
    
    class ModelUI:
    
        def __init__(self):
    
            self.par = dict()
            self.initUI()
    
        def initUI(self):
    
            self.funcPars = widgets.VBox()
    
            self.initLinear()
            self.initQuadratic()
            self.initFunc()
            self.initButton()
            self.initOutput()    
    
            self.controls = widgets.HBox([
                self.func, 
                self.funcPars, 
                self.plot
            ])
            self.UI = widgets.VBox([
                self.controls, 
                self.output
            ])
    
        def initFunc(self):
    
            self.func = widgets.Dropdown(
                description="Function:", 
                options=[
                    "Linear", 
                    "Quadratic"
                ])
            self.func.observe(self.updateFunc, "value")
    
            self.updateFunc(None)
    
        def initButton(self):
    
            self.plot = widgets.Button(description="Plot")
            self.plot.on_click(self.plotFunction)
    
        def updateFunc(self, change):
    
            if self.func.value == "Linear":
                self.funcPars.children = self.linPars
                self.par['func'] = "Linear"
            elif self.func.value == "Quadratic":
                self.funcPars.children = self.quadPars
                self.par['func'] = "Quadratic"
            else:
                pass
    
        def initLinear(self):
    
            self.m = widgets.FloatSlider(
                description="m", 
                min=-10, max=10, value=2)
            self.k = widgets.FloatSlider(
                description="k", 
                min=-10, max=10, value=1)
            self.linPars = [self.m, self.k]
    
            self.m.observe(self.updateLinear, "value")
            self.k.observe(self.updateLinear, "value")
    
            self.updateLinear(None)
    
        def updateLinear(self, change):
    
            self.par['m'] = self.m.value
            self.par['k'] = self.k.value
    
        def initQuadratic(self):
    
            self.a = widgets.FloatSlider(
                description="a", 
                min=-10, max=10, value=1)
            self.b = widgets.FloatSlider(
                description="b", 
                min=-10, max=10, value=2)
            self.c = widgets.FloatSlider(
                description="c", 
                min=-10, max=10, value=3)
            self.quadPars = [self.a, self.b, self.c]
    
            self.a.observe(self.updateQuadratic, "value")
            self.b.observe(self.updateQuadratic, "value")
            self.c.observe(self.updateQuadratic, "value")
    
            self.updateQuadratic(None)
    
        def updateQuadratic(self, change):
    
            self.par['a'] = self.a.value
            self.par['b'] = self.b.value
            self.par['c'] = self.c.value
    
        def initOutput(self):
    
            self.output = widgets.Output()
            self.plotFunction(None)    
    
        def plotFunction(self, change):
    
            self.function = {
                "Linear": lambda x: self.par['m']*x + self.par['k'],
                "Quadratic": lambda x: self.par['a']*x**2 + self.par['b']*x + self.par['c']
                }
            with self.output:
                ipd.clear_output()
                xvals = [ i/10 for i in range(-100,100)]
                yvals = list(map(self.function[self.par['func']], xvals))
                plt.plot(xvals,yvals)
                plt.show()
    
        def _ipython_display_(self):
    
            display(self.UI)
    
    ModelUI()
    

0 个答案:

没有答案