Skip to content

Commit

Permalink
layout parameter passed to widget, widget is disabled if in inputs (n…
Browse files Browse the repository at this point in the history
…ot targets), new TextInnotation and _WidgetInnotation base class
  • Loading branch information
danlester committed Mar 21, 2019
1 parent 46ab973 commit 4acb925
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 52 deletions.
35 changes: 0 additions & 35 deletions Example/Examples.ipynb
Expand Up @@ -27,11 +27,6 @@
"outputs": [ "outputs": [
{ {
"data": { "data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "d9479625b29e465d958718fc1320e3e2",
"version_major": 2,
"version_minor": 0
},
"text/plain": [ "text/plain": [
"Innotater(children=(HBox(children=(VBox(children=(ImagePad(value=b'\\xff\\xd8\\xff\\xe0\\x00\\x10JFIF\\x00\\x01\\x01\\x0…" "Innotater(children=(HBox(children=(VBox(children=(ImagePad(value=b'\\xff\\xd8\\xff\\xe0\\x00\\x10JFIF\\x00\\x01\\x01\\x0…"
] ]
Expand Down Expand Up @@ -236,11 +231,6 @@
"outputs": [ "outputs": [
{ {
"data": { "data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "ff55e86725f946668c74c7c9ffe3b032",
"version_major": 2,
"version_minor": 0
},
"text/plain": [ "text/plain": [
"Innotater(children=(HBox(children=(VBox(children=(ImagePad(value=b'\\x89PNG\\r\\n\\x1a\\n\\x00\\x00\\x00\\rIHDR\\x00\\x00…" "Innotater(children=(HBox(children=(VBox(children=(ImagePad(value=b'\\x89PNG\\r\\n\\x1a\\n\\x00\\x00\\x00\\rIHDR\\x00\\x00…"
] ]
Expand Down Expand Up @@ -312,11 +302,6 @@
"outputs": [ "outputs": [
{ {
"data": { "data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "8641000664c0492994a8050fafa3902b",
"version_major": 2,
"version_minor": 0
},
"text/plain": [ "text/plain": [
"Innotater(children=(HBox(children=(VBox(children=(ImagePad(value=b'\\x89PNG\\r\\n\\x1a\\n\\x00\\x00\\x00\\rIHDR\\x00\\x00…" "Innotater(children=(HBox(children=(VBox(children=(ImagePad(value=b'\\x89PNG\\r\\n\\x1a\\n\\x00\\x00\\x00\\rIHDR\\x00\\x00…"
] ]
Expand Down Expand Up @@ -353,11 +338,6 @@
"outputs": [ "outputs": [
{ {
"data": { "data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "fd0fdfb9cb0c40eaa71d924fe11c002e",
"version_major": 2,
"version_minor": 0
},
"text/plain": [ "text/plain": [
"Innotater(children=(HBox(children=(VBox(children=(ImagePad(value=b'\\xff\\xd8\\xff\\xe0\\x00\\x10JFIF\\x00\\x01\\x01\\x0…" "Innotater(children=(HBox(children=(VBox(children=(ImagePad(value=b'\\xff\\xd8\\xff\\xe0\\x00\\x10JFIF\\x00\\x01\\x01\\x0…"
] ]
Expand Down Expand Up @@ -415,11 +395,6 @@
"outputs": [ "outputs": [
{ {
"data": { "data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "85c9052ba0f146d798610588e422f074",
"version_major": 2,
"version_minor": 0
},
"text/plain": [ "text/plain": [
"Innotater(children=(HBox(children=(VBox(children=(ImagePad(value=b'\\xff\\xd8\\xff\\xe0\\x00\\x10JFIF\\x00\\x01\\x01\\x0…" "Innotater(children=(HBox(children=(VBox(children=(ImagePad(value=b'\\xff\\xd8\\xff\\xe0\\x00\\x10JFIF\\x00\\x01\\x01\\x0…"
] ]
Expand Down Expand Up @@ -485,11 +460,6 @@
"outputs": [ "outputs": [
{ {
"data": { "data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "46589a2724f545358a2e18c5aecfecae",
"version_major": 2,
"version_minor": 0
},
"text/plain": [ "text/plain": [
"Innotater(children=(HBox(children=(VBox(children=(ImagePad(value=b'\\x89PNG\\r\\n\\x1a\\n\\x00\\x00\\x00\\rIHDR\\x00\\x00…" "Innotater(children=(HBox(children=(VBox(children=(ImagePad(value=b'\\x89PNG\\r\\n\\x1a\\n\\x00\\x00\\x00\\rIHDR\\x00\\x00…"
] ]
Expand Down Expand Up @@ -547,11 +517,6 @@
"outputs": [ "outputs": [
{ {
"data": { "data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "d462727029764bdca7ae3d3354c49407",
"version_major": 2,
"version_minor": 0
},
"text/plain": [ "text/plain": [
"Innotater(children=(HBox(children=(VBox(children=(ImagePad(value=b'\\x89PNG\\r\\n\\x1a\\n\\x00\\x00\\x00\\rIHDR\\x00\\x00…" "Innotater(children=(HBox(children=(VBox(children=(ImagePad(value=b'\\x89PNG\\r\\n\\x1a\\n\\x00\\x00\\x00\\rIHDR\\x00\\x00…"
] ]
Expand Down
10 changes: 7 additions & 3 deletions README.md
Expand Up @@ -153,14 +153,16 @@ This is the base class (not to be instantiated directly).
The general constructor format for subclasses is: 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. 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). `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 #### ImageInnotation


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


Extra optional parameters: 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 #### BinaryClassInnotation


Expand Down
11 changes: 8 additions & 3 deletions RELEASE.md
Expand Up @@ -4,13 +4,18 @@ Update __meta__.py (set release version, remove 'dev')
Also change version number in package.json Also change version number in package.json
git add the __meta__.py file and git commit git add the __meta__.py file and git commit
delete dist folder delete dist folder

`python setup.py sdist` `python setup.py sdist`

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


git add and git commit 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: - To release a new version of jupyter-innotater on NPM:
Expand Down
2 changes: 1 addition & 1 deletion jupyter-innotater/js/package.json
@@ -1,6 +1,6 @@
{ {
"name": "jupyter-innotater", "name": "jupyter-innotater",
"version": "0.1.2", "version": "0.1.3",
"description": "An Inline Data Annotator for Jupyter", "description": "An Inline Data Annotator for Jupyter",
"author": "danlester", "author": "danlester",
"license": "MIT", "license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion jupyter-innotater/jupyter_innotater/__meta__.py
Expand Up @@ -13,5 +13,5 @@ def _get_version(version_info):
# meta data - change dev to final for release # meta data - change dev to final for release
# also change in package.json # also change in package.json


version_info = (0, 1, 2, 'final', 0) version_info = (0, 1, 3, 'alpha', 0)
__version__ = _get_version(version_info) __version__ = _get_version(version_info)
64 changes: 55 additions & 9 deletions jupyter-innotater/jupyter_innotater/data.py
@@ -1,5 +1,5 @@
from .imagewidget import ImagePad from .imagewidget import ImagePad
from ipywidgets import Checkbox, Select, Text from ipywidgets import Checkbox, Select, Text, Dropdown
import re import re
from pathlib import Path from pathlib import Path


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


self.widget = None self.widget = None


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

self.disabled = False

def get_name(self): def get_name(self):
return self.name return self.name


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


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


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

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


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


def _create_widget(self): 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): def update_ui(self, uindex):
if self.transform is None: if self.transform is None:
Expand Down Expand Up @@ -134,7 +142,7 @@ def post_widget_create(self, datamanager):
self.sourcedw.get_widget().observe(self.rectChanged, names='rect') self.sourcedw.get_widget().observe(self.rectChanged, names='rect')


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


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


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

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


def _create_widget(self): 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): def _calc_class_index(self, uindex):
if self.datadepth == 'onehot': if self.datadepth == 'onehot':
Expand All @@ -218,9 +230,6 @@ def _calc_class_index(self, uindex):
def update_ui(self, uindex): def update_ui(self, uindex):
self.get_widget().value = self.classes[self._calc_class_index(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): def update_data(self, uindex):
newval = self._get_widget_value() newval = self._get_widget_value()
old_class_index = self._calc_class_index(uindex) old_class_index = self._calc_class_index(uindex)
Expand All @@ -242,10 +251,47 @@ def _guess_classes(self):
self.classes = ['False', 'True'] self.classes = ['False', 'True']


def _create_widget(self): 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): def update_ui(self, uindex):
self.get_widget().value = bool(self._calc_class_index(uindex) == 1) self.get_widget().value = bool(self._calc_class_index(uindex) == 1)


def _get_widget_value(self): def _get_widget_value(self):
return self.classes[self.get_widget().value and 1 or 0] 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
3 changes: 3 additions & 0 deletions jupyter-innotater/jupyter_innotater/manager.py
Expand Up @@ -68,3 +68,6 @@ def get_targets(self):


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

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

0 comments on commit 4acb925

Please sign in to comment.