Skip to content
Permalink
Browse files

layout parameter passed to widget, widget is disabled if in inputs (n…

…ot targets), new TextInnotation and _WidgetInnotation base class
  • Loading branch information...
danlester committed Mar 21, 2019
1 parent 46ab973 commit 4acb925ac12d9596dd417d8e8271ba4e7fbcb1e3
@@ -27,11 +27,6 @@
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "d9479625b29e465d958718fc1320e3e2",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Innotater(children=(HBox(children=(VBox(children=(ImagePad(value=b'\\xff\\xd8\\xff\\xe0\\x00\\x10JFIF\\x00\\x01\\x01\\x0…"
]
@@ -236,11 +231,6 @@
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "ff55e86725f946668c74c7c9ffe3b032",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Innotater(children=(HBox(children=(VBox(children=(ImagePad(value=b'\\x89PNG\\r\\n\\x1a\\n\\x00\\x00\\x00\\rIHDR\\x00\\x00…"
]
@@ -312,11 +302,6 @@
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "8641000664c0492994a8050fafa3902b",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Innotater(children=(HBox(children=(VBox(children=(ImagePad(value=b'\\x89PNG\\r\\n\\x1a\\n\\x00\\x00\\x00\\rIHDR\\x00\\x00…"
]
@@ -353,11 +338,6 @@
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "fd0fdfb9cb0c40eaa71d924fe11c002e",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Innotater(children=(HBox(children=(VBox(children=(ImagePad(value=b'\\xff\\xd8\\xff\\xe0\\x00\\x10JFIF\\x00\\x01\\x01\\x0…"
]
@@ -415,11 +395,6 @@
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "85c9052ba0f146d798610588e422f074",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Innotater(children=(HBox(children=(VBox(children=(ImagePad(value=b'\\xff\\xd8\\xff\\xe0\\x00\\x10JFIF\\x00\\x01\\x01\\x0…"
]
@@ -485,11 +460,6 @@
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "46589a2724f545358a2e18c5aecfecae",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Innotater(children=(HBox(children=(VBox(children=(ImagePad(value=b'\\x89PNG\\r\\n\\x1a\\n\\x00\\x00\\x00\\rIHDR\\x00\\x00…"
]
@@ -547,11 +517,6 @@
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "d462727029764bdca7ae3d3354c49407",
"version_major": 2,
"version_minor": 0
},
"text/plain": [
"Innotater(children=(HBox(children=(VBox(children=(ImagePad(value=b'\\x89PNG\\r\\n\\x1a\\n\\x00\\x00\\x00\\rIHDR\\x00\\x00…"
]
@@ -153,14 +153,16 @@ This is the base class (not to be instantiated directly).
The general constructor format for subclasses is:

```
Innotation( <array_like> data, [name=<string>,] [desc=<string>,])
Innotation( <array_like> data, [name=<string>,] [desc=<string>,] [layout=<dict>,])
```

Optionally, data can be specified as a `data=` keyword argument, in which case the positional data argument should be omitted.

`name` is optional unless required so that the Innotation can be specified as the source for another Innotation (e.g. to link the Bounding Box data with the image to which it applies).

`desc` is also optional, and defaults to the same value as `name`. It may be displayed as a text label next to the data in the widget.
`desc` is also optional, and defaults to the same value as `name`. It may be displayed as a text label next to the data in the widget.

`layout` is an optional dictionary of CSS styles to pass on to the underlying widget, for example layout={'width':'100px'}

#### ImageInnotation

@@ -207,7 +209,9 @@ Displays a list selection box so the user can choose one highlighted option. Cur

Extra optional parameters:

`classes` - an array of string values containing text to display in place of the numerical class indices.
`classes` - an array of string values containing text to display in place of the numerical class indices. Will try to infer from data if omitted.

`dropdown` - boolean to indicate if the widget should be shown as a Dropdown list (True) or the default value of a larger always-open list (False)

#### BinaryClassInnotation

@@ -4,13 +4,18 @@ Update __meta__.py (set release version, remove 'dev')
Also change version number in package.json
git add the __meta__.py file and git commit
delete dist folder

`python setup.py sdist`

`twine upload dist/*`
`git tag -a X.X.X -m 'comment'`

git add and git commit
git push
git push --tags

`git tag -a X.X.X -m 'comment'`

`git push`

`git push --tags`


- To release a new version of jupyter-innotater on NPM:
@@ -1,6 +1,6 @@
{
"name": "jupyter-innotater",
"version": "0.1.2",
"version": "0.1.3",
"description": "An Inline Data Annotator for Jupyter",
"author": "danlester",
"license": "MIT",
@@ -13,5 +13,5 @@ def _get_version(version_info):
# meta data - change dev to final for release
# also change in package.json

version_info = (0, 1, 2, 'final', 0)
version_info = (0, 1, 3, 'alpha', 0)
__version__ = _get_version(version_info)
@@ -1,5 +1,5 @@
from .imagewidget import ImagePad
from ipywidgets import Checkbox, Select, Text
from ipywidgets import Checkbox, Select, Text, Dropdown
import re
from pathlib import Path

@@ -29,11 +29,16 @@ def __init__(self, *args, **kwargs):

self.widget = None

self.layout = kwargs.get('layout', {})

self.disabled = False

def get_name(self):
return self.name

def post_register(self, datamanager):
pass
if datamanager.is_input(self):
self.disabled = True

def post_widget_create(self, datamanager):
pass
@@ -46,6 +51,9 @@ def get_widget(self):
self.widget = self._create_widget() # on derived class
return self.widget

def _get_widget_value(self):
return self.get_widget().value

def update_ui(self, uindex):
raise Exception('Do not call update_ui on base class')

@@ -66,7 +74,7 @@ def __init__(self, *args, **kwargs):
self.transform = kwargs.get('transform', None)

def _create_widget(self):
return ImagePad(wantwidth=self.width, wantheight=self.height)
return ImagePad(wantwidth=self.width, wantheight=self.height, layout=self.layout, disabled=self.disabled)

def update_ui(self, uindex):
if self.transform is None:
@@ -134,7 +142,7 @@ def post_widget_create(self, datamanager):
self.sourcedw.get_widget().observe(self.rectChanged, names='rect')

def _create_widget(self):
return Text()
return Text(layout=self.layout, disabled=self.disabled)

def update_ui(self, uindex):
self.get_widget().value = self._value_to_str(self.data[uindex])
@@ -191,6 +199,8 @@ def __init__(self, *args, **kwargs):
# Guess the range of classes
self._guess_classes()

self.dropdown = kwargs.get('dropdown', False)

def _guess_classes(self):
if self.datadepth == 'onehot':
m = len(self.data[0])-1
@@ -205,7 +215,9 @@ def _guess_classes(self):
self.classes = [str(i) for i in range(m+1)]

def _create_widget(self):
return Select(options=self.classes)
if self.dropdown:
return Dropdown(options=self.classes, layout=self.layout, disabled=self.disabled)
return Select(options=self.classes, layout=self.layout, disabled=self.disabled)

def _calc_class_index(self, uindex):
if self.datadepth == 'onehot':
@@ -218,9 +230,6 @@ def _calc_class_index(self, uindex):
def update_ui(self, uindex):
self.get_widget().value = self.classes[self._calc_class_index(uindex)]

def _get_widget_value(self):
return self.get_widget().value

def update_data(self, uindex):
newval = self._get_widget_value()
old_class_index = self._calc_class_index(uindex)
@@ -242,10 +251,47 @@ def _guess_classes(self):
self.classes = ['False', 'True']

def _create_widget(self):
return Checkbox(description=self.desc)
return Checkbox(description=self.desc, layout=self.layout, disabled=self.disabled)

def update_ui(self, uindex):
self.get_widget().value = bool(self._calc_class_index(uindex) == 1)

def _get_widget_value(self):
return self.classes[self.get_widget().value and 1 or 0]


class TextInnotation(Innotation):

def _create_widget(self):
return Text(layout=self.layout, disabled=self.disabled)

def update_ui(self, uindex):
self.get_widget().value = str(self.data[uindex])

def update_data(self, uindex):
newval = str(self._get_widget_value())
if newval != str(self.data[uindex]):
self.data[uindex] = newval


class _WidgetInnotation(Innotation):
"""
Allow embeding of an arbitrary widget object, e.g. for text display
Must still have a data attribute of correct len, even if dummy values
"""

def __init__(self, *args, **kwargs):

super().__init__(*args, **kwargs)
if 'widget' not in kwargs:
raise Exception(f'{self.__class__} requires a widget argument')
self.widget = kwargs['widget']

def _create_widget(self):
return self.widget

def update_ui(self, uindex):
pass

def update_data(self, uindex):
pass
@@ -68,3 +68,6 @@ def get_targets(self):

def get_all(self):
return self.alldws.values()

def is_input(self, dw):
return dw in self.inputs

0 comments on commit 4acb925

Please sign in to comment.
You can’t perform that action at this time.