Skip to content

Commit

Permalink
Implementation of new Annotator API (#21)
Browse files Browse the repository at this point in the history
  • Loading branch information
hoxbro authored Sep 19, 2023
1 parent a502bdb commit a8fafa6
Show file tree
Hide file tree
Showing 15 changed files with 1,115 additions and 536 deletions.
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

0 comments on commit a8fafa6

Please sign in to comment.