Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementation of new Annotator API #21

Merged
merged 61 commits into from
Sep 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
6b238f6
First iteration of decoupling Annotator and Element
hoxbro Aug 29, 2023
2be2ae2
Make region_editor and selection_editor singleton
hoxbro Aug 29, 2023
b5bf2c5
Add some typehints
hoxbro Aug 29, 2023
8d87ffc
Added _make_empty_element
hoxbro Aug 30, 2023
ef864c8
Refactor and type hints
hoxbro Aug 30, 2023
16f5764
Small refactor and update code
hoxbro Aug 30, 2023
e827965
Handle multiple dims
hoxbro Aug 30, 2023
8f31a1e
Add spec as input
hoxbro Aug 30, 2023
2ce9ff9
Comment out require import for now
hoxbro Aug 31, 2023
de607df
Implement spec parameter
hoxbro Aug 31, 2023
3bce132
Add_annotation now support new regions and spec format
hoxbro Aug 31, 2023
96cfcaf
Don't use same object for self._last_region
hoxbro Aug 31, 2023
881fda0
Handle combining region_df and field_df in annotations_table
hoxbro Aug 31, 2023
d27c32f
Update Annotator to work with new regions and spec format
hoxbro Aug 31, 2023
e58f26a
Add some docstring
hoxbro Sep 1, 2023
098cbb1
Change 'set_{range, point}' to use 'set_regions' and remove '_set_reg…
hoxbro Sep 1, 2023
8f8669c
Update tests to new framework
hoxbro Sep 1, 2023
6034f24
Update code to fix test
hoxbro Sep 1, 2023
b65598f
Skip test which does not work with new framework
hoxbro Sep 1, 2023
9f9a292
Handle empty 2d range
hoxbro Sep 1, 2023
84eeabb
Set regions function call now update the element
hoxbro Sep 1, 2023
8673b96
Test to verify set_regions gives a value in plot
hoxbro Sep 1, 2023
b276285
Add annotation_type to elements for debugging purposes
hoxbro Sep 3, 2023
08d9c73
Remove annotation type and clean up test
hoxbro Sep 4, 2023
090d963
Add more table tests
hoxbro Sep 4, 2023
ae50442
Better handling of datetime_types
hoxbro Sep 4, 2023
3f8cb16
Remove kdims_dtypes to selective AnnotatorElement
hoxbro Sep 4, 2023
40f08f7
Update multiple_annotator
hoxbro Sep 4, 2023
b7841a8
Add test for multiple element annotation
hoxbro Sep 4, 2023
147197c
Add test_commit_update_set_region
hoxbro Sep 4, 2023
65cba17
Remove region_types to selective AnnotatorElement
hoxbro Sep 4, 2023
0e9a84d
Handle empty region
hoxbro Sep 4, 2023
5369cbd
Call super() in select_by_index
hoxbro Sep 4, 2023
aa5f396
Remove annotation_table as parameter
hoxbro Sep 4, 2023
8db06bc
Rename self.anno to self.annotator and make it a weakref.proxy
hoxbro Sep 4, 2023
ea3c5d8
Add initial define_annotations
hoxbro Sep 4, 2023
29aae06
Add get_element
hoxbro Sep 4, 2023
2e45974
Update Basics example with new API
hoxbro Sep 5, 2023
96d47b2
Update Basics_2D example with new API
hoxbro Sep 5, 2023
3daa871
Add barebone examples of multiplot
hoxbro Sep 5, 2023
72d2a6d
Supress multiple competing tools warning
hoxbro Sep 5, 2023
5b2f287
Add _add_annotation and putting some legacy print statement
hoxbro Sep 5, 2023
0dcba94
Small updates to multiplot example
hoxbro Sep 5, 2023
ebaaded
Add unittest for define_annotations
hoxbro Sep 5, 2023
18bfebe
Add note for future improvement
hoxbro Sep 5, 2023
beeb95f
Add check to see if key in spec before creating an annotator element
hoxbro Sep 5, 2023
83e8232
Add logic around active tools even if it does not work right now
hoxbro Sep 6, 2023
a15d3be
Add filterwarning to pyproject.toml
hoxbro Sep 6, 2023
4ef143e
Add HoverTool back
hoxbro Sep 6, 2023
8cb32a9
Handle no region
hoxbro Sep 6, 2023
c146bfe
Add construction sign to sections in examples
hoxbro Sep 7, 2023
f8adb91
Improve deleting selected index
hoxbro Sep 7, 2023
f532950
small changes
hoxbro Sep 7, 2023
acacda7
Pin Pandas<2.1
hoxbro Sep 12, 2023
fd4e903
Ignore wrong warning in older version of Numpy
hoxbro Sep 13, 2023
a251d77
Applied suggested edit
jlstevens Sep 18, 2023
59f63a4
Rename to normalize_spec
hoxbro Sep 19, 2023
9336f06
Remove mention of define_fields
hoxbro Sep 19, 2023
7e45ce1
Change single back to point
hoxbro Sep 19, 2023
06d41f4
Rename multi to geometry
hoxbro Sep 19, 2023
658b40f
Rename AnnotatorElement to AnnotationDisplay
hoxbro Sep 19, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 15 additions & 70 deletions examples/Basics.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,6 @@
"from holonote.annotate import Annotator"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "042914f0-cb8d-427d-b1e1-3a2056bc392e",
"metadata": {},
"outputs": [],
"source": [
"hv.opts.defaults(hv.opts.Rectangles(apply_ranges=False))"
]
},
{
"cell_type": "markdown",
"id": "2c4a4b17-173b-43c2-ab20-251c459029fe",
Expand Down Expand Up @@ -97,7 +87,7 @@
"metadata": {},
"outputs": [],
"source": [
"annotator.overlay() # If you have a database file generated by a previous commit, your annotations will now be displayed"
"annotator * speed_curve # If you have a database file generated by a previous commit, your annotations will now be displayed"
]
},
{
Expand Down Expand Up @@ -151,7 +141,7 @@
"metadata": {},
"outputs": [],
"source": [
"annotator.set_range(np.datetime64('2022-06-06'), np.datetime64('2022-06-08'))\n",
"annotator.set_regions(TIME=(np.datetime64('2022-06-06'), np.datetime64('2022-06-08')))\n",
"annotator.add_annotation(description='A programmatically defined annotation')"
]
},
Expand Down Expand Up @@ -291,7 +281,7 @@
"metadata": {},
"outputs": [],
"source": [
"annotator.set_range(np.datetime64('2022-06-15'), np.datetime64('2022-06-18'))\n",
"annotator.set_regions(TIME=(np.datetime64('2022-06-15'), np.datetime64('2022-06-18')))\n",
"annotator.add_annotation(description='An annotation description we will update...')"
]
},
Expand Down Expand Up @@ -359,7 +349,7 @@
"source": [
"input_uuid = 'deadcafe'\n",
"description = f'Annotation with set UUID {input_uuid!r}'\n",
"annotator.set_range(np.datetime64('2022-06-10'), np.datetime64('2022-06-13'))\n",
"annotator.set_regions(TIME=(np.datetime64('2022-06-10'), np.datetime64('2022-06-13')))\n",
"annotator.add_annotation(description=description, uuid=input_uuid)\n",
"description"
]
Expand Down Expand Up @@ -422,9 +412,9 @@
"metadata": {},
"outputs": [],
"source": [
"starts = [np.datetime64('2022-06-%.2d' % d) for d in range(6,15, 4)]\n",
"ends = [np.datetime64('2022-06-%.2d' % (d+2)) for d in range(6,15, 4)]\n",
"descriptions = ['Annotation %d' % d for d in range(3)]\n",
"starts = pd.date_range(\"2022-06-06\", freq=\"3D\", periods=3)\n",
"ends = starts + pd.Timedelta(\"2D\")\n",
"descriptions = [\"Annotation 0\", \"Annotation 1\", \"Annotation 2\"]\n",
"data = pd.DataFrame({'start':starts, 'end':ends, 'description':descriptions})\n",
"data"
]
Expand All @@ -434,7 +424,7 @@
"id": "fc931d2b-285a-4fa3-944d-f17c39196344",
"metadata": {},
"source": [
"To load this data, we *first* need to define the data in the annotation fields (for this annotator this is the `description` field):"
"To load this data, we use `define_annotations` and pass in the columns from the DataFrame. "
]
},
{
Expand All @@ -444,40 +434,15 @@
"metadata": {},
"outputs": [],
"source": [
"annotator.define_fields(data[['description']])"
]
},
{
"cell_type": "markdown",
"id": "c2683667-6abb-4b97-955f-9192f78ce3f2",
"metadata": {},
"source": [
"Now we can define the starts and ends of our annotation regions as follows:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3ba550f2-3695-4999-b66d-ce70e087f09d",
"metadata": {},
"outputs": [],
"source": [
"annotator.define_ranges(data['start'], data['end'])"
"annotator.define_annotations(data, TIME=(\"start\", \"end\"), description=\"description\")"
]
},
{
"cell_type": "markdown",
"id": "9710c385-7ff6-43f7-ac41-aee2aa990670",
"metadata": {},
"source": [
"The `DataFrame`/`Series` index (here the default pandas index) is what links our ranges to their corresponding field entries.\n",
"\n",
"Note the following rules:\n",
"\n",
"1. The index values supplied to the `define_` region methods must first be defined by `define_fields`.\n",
"2. Before we can call the `.commit` method, every index supplied to `define_fields` must have been given at least one region.\n",
"\n",
"As with `add_annotation`, the annotator automatically create uuid primary key values and the original index is ignored:"
"If a column name matches with a name of region or a field it will be used this means the `description=\"description` in the above line is not needed. "
]
},
{
Expand All @@ -495,8 +460,6 @@
"id": "245eff10-f59e-4b00-b933-68aafdd38499",
"metadata": {},
"source": [
"This can be overridden by supplying `preserve_index=True` to the `define_fields` method as now described.\n",
"\n",
"### Preserving the index"
]
},
Expand All @@ -505,7 +468,7 @@
"id": "fda1a724-11e9-40e4-ae72-d2922c240fd0",
"metadata": {},
"source": [
"Sometimes the annotations you are loading have meaningful primary keys defined elsewhere (e.g. some other pre-existing database) that need to be preserved. This is possible by supplying `preserve_index=True` to the `define_fields` method.\n",
"Sometimes the annotations you are loading have meaningful primary keys defined elsewhere (e.g. some other pre-existing database) that need to be preserved. This is possible by supplying `index=True` in the `define_annotations` method.\n",
"\n",
"*Note: The user bears the same responsibilities for using appropriate index values as described in the ***Caveats when picking your own primary keys*** section!*\n"
]
Expand All @@ -530,7 +493,7 @@
"id": "4053d426-770d-4309-b8c4-582b76f11d3e",
"metadata": {},
"source": [
"To preserve the index call, the `define_fields` must be called with `preserve_index=True`:"
"To preserve the index call, the `define_annotations` must be called with `index=True`:"
]
},
{
Expand All @@ -540,25 +503,7 @@
"metadata": {},
"outputs": [],
"source": [
"annotator.define_fields(indexed_data[['description']], preserve_index=True)"
]
},
{
"cell_type": "markdown",
"id": "1ee25eee-df47-440d-b5bc-cc7bfade3f9f",
"metadata": {},
"source": [
"Now we can call `define_ranges` as before:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b555fff9-9e8b-48ed-878c-b39a49714a97",
"metadata": {},
"outputs": [],
"source": [
"annotator.define_ranges(indexed_data['start'], indexed_data['end'])"
"annotator.define_annotations(indexed_data, TIME=(\"start\", \"end\"), description=\"description\", index=True)"
]
},
{
Expand Down Expand Up @@ -586,7 +531,7 @@
"id": "57962a14-32be-4239-9ad3-f9eee5d18158",
"metadata": {},
"source": [
"## Selecting and highlighting annotations\n",
"## 🚧 Selecting and highlighting annotations\n",
"\n",
"Earlier we styled the indicators with `color='red', alpha=0.2`. To highlight a select a specific indicator, we can create a dimension expression to assign selected and non-selected indicators different values. Here we have a highlighter that uses a value of `0.6` for selected indicators and `0.1` for non-selected indicators. We can then apply these values to the `alpha` option:"
]
Expand Down Expand Up @@ -687,7 +632,7 @@
"id": "16134a64-1347-4ebe-909a-716f55c520ac",
"metadata": {},
"source": [
"## Using `.overlay`\n",
"## 🚧 Using `.overlay`\n",
"\n",
"The `.overlay` method is a shortcut to building the following overlay:\n",
"\n",
Expand Down
73 changes: 19 additions & 54 deletions examples/Basics_2D.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
"metadata": {},
"outputs": [],
"source": [
"annotator = Annotator(image, fields=['description'], region_types=['Range'])"
"annotator = Annotator(image, fields=['description'])"
]
},
{
Expand All @@ -92,7 +92,7 @@
"metadata": {},
"outputs": [],
"source": [
"annotator.overlay()"
"annotator * image"
]
},
{
Expand All @@ -102,13 +102,7 @@
"source": [
"The default output of `.overlay` is designed to be useful by default. Options on controlling the displayed layers and their styles can be found in the **Using `.overlay` section**.\n",
"\n",
"**Note** The tools made available by the region editor is appropriate to the dimensionality of the element (here, a single key dimension on the x-axis).\n",
"\n",
"Also note that if we had used the key dimension type specification in the constructor instead of the element, the following would be equivalent:\n",
"\n",
"```python\n",
"annotator.overlay(element=speed_curve)\n",
"```"
"**Note** The tools made available by the region editor is appropriate to the dimensionality of the element (here, a single key dimension on the x-axis)."
]
},
{
Expand Down Expand Up @@ -154,7 +148,7 @@
"metadata": {},
"outputs": [],
"source": [
"annotator.set_range(-0.25,0.25,-0.25,0.25)\n",
"annotator.set_regions(A=(-0.25,0.25),B=(-0.25,0.25))\n",
"annotator.add_annotation(description='A programmatically defined annotation')"
]
},
Expand Down Expand Up @@ -284,7 +278,7 @@
"metadata": {},
"outputs": [],
"source": [
"annotator.set_range(-0.35,-0.15,-0.35,-0.25)\n",
"annotator.set_regions(A=(-0.35,-0.15), B=(-0.35,-0.25))\n",
"annotator.add_annotation(description='An annotation description we will update...')"
]
},
Expand Down Expand Up @@ -352,7 +346,7 @@
"source": [
"input_uuid = 'deadcafe'\n",
"description = f'Annotation with set UUID {input_uuid!r}'\n",
"annotator.set_range(0.35,0.15,0.35,0.25)\n",
"annotator.set_regions(A=(-0.35,-0.15), B=(-0.35,-0.25))\n",
"annotator.add_annotation(description=description, uuid=input_uuid)\n",
"description"
]
Expand Down Expand Up @@ -417,7 +411,7 @@
"source": [
"startx, endx = [-0.1,-0.2,-0.3], [0.1,0.2,0.3]\n",
"starty, endy = [-0.2,-0.3,-0.4], [0.2,0.3,0.4]\n",
"descriptions = ['Annotation %d' % d for d in range(3)]\n",
"descriptions = [\"Annotation 0\", \"Annotation 1\", \"Annotation 2\"]\n",
"data = pd.DataFrame({'startx':startx, 'endx':endx, 'starty':starty, 'endy':endy, 'description':descriptions})\n",
"data"
]
Expand All @@ -427,7 +421,7 @@
"id": "fc931d2b-285a-4fa3-944d-f17c39196344",
"metadata": {},
"source": [
"To load this data, we *first* need to define the data in the annotation fields (for this annotator this is the `description` field):"
"To load this data, we use `define_annotations` and pass in the columns from the DataFrame. "
]
},
{
Expand All @@ -437,40 +431,15 @@
"metadata": {},
"outputs": [],
"source": [
"annotator.define_fields(data[['description']])"
"annotator.define_annotations(data, A=(\"startx\", \"endx\"), B=(\"starty\", \"endy\"), description=\"description\")"
]
},
{
"cell_type": "markdown",
"id": "c2683667-6abb-4b97-955f-9192f78ce3f2",
"id": "949c7dd8",
"metadata": {},
"source": [
"Now we can define the starts and ends of our annotation regions as follows:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3ba550f2-3695-4999-b66d-ce70e087f09d",
"metadata": {},
"outputs": [],
"source": [
"annotator.define_ranges(data['startx'], data['endx'], data['starty'], data['endy'])"
]
},
{
"cell_type": "markdown",
"id": "9710c385-7ff6-43f7-ac41-aee2aa990670",
"metadata": {},
"source": [
"The `DataFrame`/`Series` index (here the default pandas index) is what links our ranges to their corresponding field entries.\n",
"\n",
"Note the following rules:\n",
"\n",
"1. The index values supplied to the `define_` region methods must first be defined by `define_fields`.\n",
"2. Before we can call the `.commit` method, every index supplied to `define_fields` must have been given at least one region.\n",
"\n",
"As with `add_annotation`, the annotator automatically create uuid primary key values and the original index is ignored:"
"If a column name matches with a name of region or a field it will be used this means the `description=\"description` in the above line is not needed. "
]
},
{
Expand All @@ -488,8 +457,6 @@
"id": "245eff10-f59e-4b00-b933-68aafdd38499",
"metadata": {},
"source": [
"This can be overridden by supplying `preserve_index=True` to the `define_fields` method as now described.\n",
"\n",
"### Preserving the index"
]
},
Expand All @@ -498,7 +465,7 @@
"id": "fda1a724-11e9-40e4-ae72-d2922c240fd0",
"metadata": {},
"source": [
"Sometimes the annotations you are loading have meaningful primary keys defined elsewhere (e.g. some other pre-existing database) that need to be preserved. This is possible by supplying `preserve_index=True` to the `define_fields` method.\n",
"Sometimes the annotations you are loading have meaningful primary keys defined elsewhere (e.g. some other pre-existing database) that need to be preserved. This is possible by supplying `index=True` in the `define_annotations` method.\n",
"\n",
"*Note: The user bears the same responsibilities for using appropriate index values as described in the ***Caveats when picking your own primary keys*** section!*\n"
]
Expand All @@ -518,23 +485,21 @@
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3303236f-faf3-4ace-b18d-6e3d81984f3d",
"cell_type": "markdown",
"id": "dfbaa70c",
"metadata": {},
"outputs": [],
"source": [
"annotator.define_fields(indexed_data[['description']], preserve_index=True)"
"To preserve the index call, the `define_annotations` must be called with `index=True`:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "b555fff9-9e8b-48ed-878c-b39a49714a97",
"id": "3303236f-faf3-4ace-b18d-6e3d81984f3d",
"metadata": {},
"outputs": [],
"source": [
"annotator.define_ranges(indexed_data['startx'], indexed_data['endx'], indexed_data['starty'], indexed_data['endy'])"
"annotator.define_annotations(indexed_data, A=(\"startx\", \"endx\"), B=(\"starty\", \"endy\"), description=\"description\", index=True)"
]
},
{
Expand Down Expand Up @@ -562,7 +527,7 @@
"id": "57962a14-32be-4239-9ad3-f9eee5d18158",
"metadata": {},
"source": [
"## Selecting and highlighting annotations\n",
"## 🚧 Selecting and highlighting annotations\n",
"\n",
"Earlier we styled the indicators with `color='red', alpha=0.2`. To highlight a select a specific indicator, we can create a dimension expression to assign selected and non-selected indicators different values. Here we have a highlighter that uses a value of `0.6` for selected indicators and `0.1` for non-selected indicators. We can then apply these values to the `alpha` option:"
]
Expand Down Expand Up @@ -663,7 +628,7 @@
"id": "16134a64-1347-4ebe-909a-716f55c520ac",
"metadata": {},
"source": [
"## Using `.overlay`\n",
"## 🚧 Using `.overlay`\n",
"\n",
"The `.overlay` method is a shortcut to building the following overlay:\n",
"\n",
Expand Down
Loading