Skip to content

Commit

Permalink
#6103 python API for output containers (#6150)
Browse files Browse the repository at this point in the history
* #6103 python API for output containers

* #6103 python API for output containers

* #6103 fix NaN in plots

* polish doc
  • Loading branch information
rbidas authored and Mariusz Jurowicz committed Oct 20, 2017
1 parent 2e0b4c4 commit 38c9d5c
Show file tree
Hide file tree
Showing 8 changed files with 422 additions and 6 deletions.
1 change: 1 addition & 0 deletions beakerx/beakerx/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from .plot import *
from .easyform import *
from .tabledisplay import *
from .output_container import *
from ._version import version_info, __version__

def _jupyter_nbextension_paths():
Expand Down
88 changes: 84 additions & 4 deletions beakerx/beakerx/beakerx_widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@
# limitations under the License.

from ipywidgets import Box, DOMWidget, CoreWidget, Text, Label, Textarea, \
Button, \
Button, Widget, \
SelectMultiple, Select, Dropdown, Checkbox, HBox, \
VBox, RadioButtons, register, Layout, widget_serialization
VBox, RadioButtons, register, Layout, widget_serialization, HTML
from ipywidgets.widgets.trait_types import InstanceDict
from traitlets import Int, Unicode, Tuple, Bool, Union, List, Dict
from traitlets import Int, Unicode, Dict, Bool, Union, List
from IPython.display import display


Expand All @@ -31,6 +31,11 @@ def __init__(self, **kwargs):
super(BeakerxLayout, self).__init__(**kwargs)


class BeakerxWidget(Widget):
def __init__(self, **kwargs):
super(BeakerxWidget, self).__init__(**kwargs)


class BeakerxDOMWidget(DOMWidget):
_view_module = Unicode('beakerx').tag(sync=True)
_model_module = Unicode('beakerx').tag(sync=True)
Expand Down Expand Up @@ -109,6 +114,34 @@ def __init__(self, **kwargs):
style = None


class BeakerxHTML(HTML):
def __init__(self, *args, **kwargs):
super(BeakerxHTML, self).__init__(**kwargs)
if len(args) > 0:
self.value = args[0]

_model_module_version = Unicode('*').tag(sync=True)
_view_module_version = Unicode('*').tag(sync=True)

layout = InstanceDict(BeakerxLayout).tag(sync=True, **widget_serialization)
style = None


class BeakerxHTMLPre(HTML):
def __init__(self, **kwargs):
super(BeakerxHTMLPre, self).__init__(**kwargs)

_view_name = Unicode('HTMLPreView').tag(sync=True)
_model_name = Unicode('HTMLPreModel').tag(sync=True)
_view_module = Unicode('beakerx').tag(sync=True)
_model_module = Unicode('beakerx').tag(sync=True)
_model_module_version = Unicode('*').tag(sync=True)
_view_module_version = Unicode('*').tag(sync=True)

layout = InstanceDict(BeakerxLayout).tag(sync=True, **widget_serialization)
style = None


class BeakerxButton(Button):
def __init__(self, **kwargs):
super(BeakerxButton, self).__init__(**kwargs)
Expand All @@ -122,6 +155,7 @@ def __init__(self, **kwargs):
layout = InstanceDict(BeakerxLayout).tag(sync=True, **widget_serialization)
style = None


def actionPerformed(self, *args, **kwargs):
pass

Expand Down Expand Up @@ -181,8 +215,10 @@ def __init__(self, **kwargs):


class BeakerxHBox(HBox):
def __init__(self, **kwargs):
def __init__(self, children=None, **kwargs):
super(BeakerxHBox, self).__init__(**kwargs)
if children is not None:
self.children += tuple(children)

_view_module = Unicode('jupyter-js-widgets').tag(sync=True)
_model_module = Unicode('jupyter-js-widgets').tag(sync=True)
Expand All @@ -204,3 +240,47 @@ def __init__(self, **kwargs):

layout = InstanceDict(BeakerxLayout).tag(sync=True, **widget_serialization)
style = None


class CyclingDisplayBox(BeakerxBox):
_view_name = Unicode('CyclingDisplayBoxView').tag(sync=True)
_model_name = Unicode('CyclingDisplayBoxModel').tag(sync=True)
period = Int(5000).tag(sync=True)

def __init__(self, children):
super(CyclingDisplayBox, self).__init__()
self.children += tuple(children)

def setPeriod(self, period):
self.period = period


class GridView(BeakerxVBox):
_view_name = Unicode('GridView').tag(sync=True)
_model_name = Unicode('GridViewModel').tag(sync=True)
_view_module = Unicode('beakerx').tag(sync=True)
_model_module = Unicode('beakerx').tag(sync=True)

def __init__(self, rows):
super(GridView, self).__init__()
self.children += tuple(rows)


class SelectionContainer(BeakerxBox):
_titles = Dict().tag(sync=True)

def __init__(self, childrens, labels):
super(SelectionContainer, self).__init__()
labels_dict = dict()
for x in labels:
labels_dict[len(labels_dict)] = x
self._titles = labels_dict
self.children += tuple(childrens)


class Tab(SelectionContainer):
_view_name = Unicode('TabView').tag(sync=True)
_model_name = Unicode('TabModel').tag(sync=True)

def __init__(self, childrens, labels):
super(Tab, self).__init__(childrens, labels)
15 changes: 15 additions & 0 deletions beakerx/beakerx/output_container/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Copyright 2017 TWO SIGMA OPEN SOURCE, LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from .outputcontainer import *
155 changes: 155 additions & 0 deletions beakerx/beakerx/output_container/outputcontainer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
# Copyright 2017 TWO SIGMA OPEN SOURCE, LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from beakerx.beakerx_widgets import *
from beakerx.tabledisplay import *
from beakerx.plot.chart import *
from ipywidgets import Widget
from abc import *
from pandas import *


class OutputContainerLayoutManager:
borderDisplayed = True

def __init__(self):
pass

def setBorderDisplayed(self, borderDisplayed):
self.borderDisplayed = borderDisplayed

@abstractmethod
def display(self, output_container):
return NotImplemented

def getWidgets(self, container):
collection = []
for item in container.items:
collection.append(self.toWidget(item))
return collection

def toWidget(self, item):
if item is None:
return self.createHTML("None")

# if isinstance(item, DataFrame):
# return TableDisplay(item)

if isinstance(item, Widget):
return item

return self.createHTMLPre(item.__str__())

def createHTML(self, value):
label = BeakerxHTML()
label.value = value
return label

def createHTMLPre(self, value):
pre = BeakerxHTMLPre()
pre.value = value
return pre


class SimpleLayoutManager(OutputContainerLayoutManager):
def __init__(self):
super(SimpleLayoutManager, self).__init__()

def display(self, output_container):
for widget in self.getWidgets(output_container):
widget._ipython_display_()


class TabbedOutputContainerLayoutManager(OutputContainerLayoutManager):
def __init__(self):
super(TabbedOutputContainerLayoutManager, self).__init__()

def display(self, output_container):
widgets = self.getWidgets(output_container)
tab = Tab(widgets, output_container.labels)
tab._ipython_display_()


class CyclingOutputContainerLayoutManager(OutputContainerLayoutManager):
period = 5000

def __init__(self):
super(CyclingOutputContainerLayoutManager, self).__init__()

def setPeriod(self, miliseconds):
self.period = miliseconds

def display(self, output_container):
c = CyclingDisplayBox(self.getWidgets(output_container))
c.setPeriod(self.period)
c._ipython_display_()


class AbstractGridLayoutManager(OutputContainerLayoutManager):
columns = 0

def __init__(self, columns):
super(AbstractGridLayoutManager, self).__init__()
self.columns = columns


class GridOutputContainerLayoutManager(AbstractGridLayoutManager):
def __init__(self, columns=2):
super(GridOutputContainerLayoutManager, self).__init__(columns)

def display(self, output_container):
layout = output_container.layoutManager
columns = layout.columns

items = self.getWidgets(output_container)
rows = []
for itemIndex in range(0, len(items), columns):
rows.append(BeakerxHBox(self.createRow(columns, items, itemIndex)))

grid_view = GridView(rows)
grid_view._ipython_display_()

def createRow(self, columns, items, itemIndex):
row_items = []
for c in range(itemIndex, itemIndex + columns):
if c < len(items):
row_items.append(items[c])
else:
row_items.append(self.emptyItem())
return row_items

def emptyItem(self):
return BeakerxHBox()


class OutputContainer:
layoutManager = SimpleLayoutManager()
items = []
labels = []

def __init__(self, **kwargs):
super(OutputContainer, self).__init__(**kwargs)
self.items = []
self.labels = []

def addItem(self, item, label=None):
self.items.append(item)
self.labels.append(label)

def setLayoutManager(self, layoutManager):
if layoutManager is not None:
self.layoutManager = layoutManager

def _ipython_display_(self):
self.layoutManager.display(self)
6 changes: 5 additions & 1 deletion beakerx/beakerx/plot/chart.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,10 @@ def add(self, item):
def getYAxes(self):
return self.chart.rangeAxes

def setShowLegend(self, show):
self.chart.show_legend = show
self.model = self.chart.transform()
return self

class CategoryPlot(BeakerxDOMWidget):
_view_name = Unicode('PlotView').tag(sync=True)
Expand Down Expand Up @@ -351,7 +355,6 @@ def __init__(self, *args, **kwargs):
self.chart.type = 'TimePlot'
self.use_tool_tip = True
self.show_legend = True
self.domain_axis_label = 'Time'
time_column_default = 'time'
displayNames = getValue(kwargs, 'displayNames')
displayLines = getValue(kwargs, 'displayLines', True)
Expand All @@ -378,6 +381,7 @@ def __init__(self, *args, **kwargs):
tableData = tableData.to_dict(orient='rows')

timeColumn = getValue(kwargs, 'timeColumn', time_column_default)
self.chart.domain_axis_label = getValue(kwargs, 'xLabel', timeColumn)
if tableData is not None and columnNames is not None:
dataColumnsNames.extend(list(tableData[0]))

Expand Down
8 changes: 8 additions & 0 deletions beakerx/beakerx/plot/plotitem.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ class XYGraphics(Graphics):
def __init__(self, **kwargs):
super(XYGraphics, self).__init__(**kwargs)
defY = getValue(kwargs, 'y')

if defY is not None:
if isinstance(defY, pd.Series):
defY = defY.tolist()
Expand All @@ -132,10 +133,17 @@ def __init__(self, **kwargs):
self.x = self.x.tolist()
for idx in range(len(self.x)):
x = self.x[idx]
if isinstance(x, float) and math.isnan(x):
self.x[idx] = "NaN"
if isinstance(x, datetime) or is_date(x):
self.x[idx] = unix_time(x)

self.y = defY
if self.y is not None:
for idx in range(len(self.y)):
y = self.y[idx]
if isinstance(y, float) and math.isnan(y):
self.y[idx] = "NaN"

self.display_name = getValue(kwargs, 'displayName')
self.lod_filter = getValue(kwargs, 'lodFilter')
Expand Down
2 changes: 1 addition & 1 deletion doc/contents/EasyFormPythonDemos.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@
"metadata": {},
"outputs": [],
"source": [
"f.put(\"First\", \"Micheal\")\n",
"f.put(\"first\", \"Micheal\")\n",
"f.put(\"last\", \"Fox\")\n",
"# Read values from form\n",
"firstName = f.get(\"first\")\n",
Expand Down
Loading

0 comments on commit 38c9d5c

Please sign in to comment.