Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
7f9483c
create Label class
Gautzilla Sep 8, 2026
38eee35
add label position and size methods
Gautzilla Sep 9, 2026
978e5ae
add detection label plot
Gautzilla Sep 9, 2026
849daeb
fix default label background color
Gautzilla Sep 9, 2026
5341916
move Label text and background parameters to the corresponding kwargs…
Gautzilla Sep 10, 2026
4a0879d
add Label init test
Gautzilla Sep 10, 2026
8c7cac1
add Label get_size test for positive width and height
Gautzilla Sep 10, 2026
8f4106f
add Label get_size test for different label widths
Gautzilla Sep 10, 2026
8d38f92
add Label get_size test for different text sizes
Gautzilla Sep 10, 2026
f658b48
test that Label.get_size() removes the added artist from the Axes
Gautzilla Sep 10, 2026
70f6524
test that Label.get_text_size() removes the text from the axes after …
Gautzilla Sep 10, 2026
50c4caa
add Label.get_coordinates() tests
Gautzilla Sep 10, 2026
45e5bbe
add Label.get_rectangle() test
Gautzilla Sep 10, 2026
929121f
combine label plot conditions
Gautzilla Sep 10, 2026
5213e47
specify labels X axis types in docstrings
Gautzilla Sep 10, 2026
da02d5a
test that Detection.plot() doesn't plot a label if plot_label is set …
Gautzilla Sep 10, 2026
e78fa58
test that Detection.plot() doesn't plot a label if detection.label is…
Gautzilla Sep 10, 2026
9e09a08
improve label plot check in tests
Gautzilla Sep 10, 2026
6363ec5
test that Detection.plot() label_kwargs parameter is passed to Label …
Gautzilla Sep 10, 2026
536669c
test default label background color is detection rectangle color
Gautzilla Sep 10, 2026
4756c08
add label patch and text tests for Detection.plot(plot_label=True) call
Gautzilla Sep 10, 2026
8ceb789
fix dict name in test_detection_plot_passes_label_kwargs()
Gautzilla Sep 10, 2026
b334b67
add label plot part in working with aplose results doc page
Gautzilla Sep 11, 2026
c6537e0
fix from_csv docstring
Gautzilla Sep 11, 2026
f597443
add bug revealing test for default label color without background_kwargs
Gautzilla Sep 11, 2026
f572985
fix default label color without background_kwargs key error
Gautzilla Sep 11, 2026
21a6f2e
add label plot to APLOSE result example
Gautzilla Sep 11, 2026
b9edeb0
fix Label API doc link
Gautzilla Sep 11, 2026
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
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/source/_static/detections/label_anchors.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
73 changes: 64 additions & 9 deletions docs/source/aplose.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ The :class:`osekit.core.detection.Detection` class inherits from the :class:`ose
Plotting a detection
^^^^^^^^^^^^^^^^^^^^

Detection boxes can be plotted on spectrograms thanks to the :method:`osekit.core.detection.Detection.to_rectangle` method:
Detection boxes can be plotted on spectrograms thanks to the :meth:`osekit.core.detection.Detection.plot` method.

First, let's plot a spectrogram, and keep track of the ``Axes`` in which the spectrogram is plot (returned by the :meth:`osekit.core.spectro_data.SpectroData.plot` method):

.. code-block:: python

Expand All @@ -49,16 +51,69 @@ Detection boxes can be plotted on spectrograms thanks to the :method:`osekit.cor
sd = SpectroData(...)
detection = Detection(...)

fig, axs = plt.subplots()
# Plot the spectrogram and keep the Axes in which the plot is made
ax = sd.plot(ax=ax)


Now, we can plot the detection directly in the ``ax`` Axes.
The detection is plotted as a `matplotlib Rectangle <https://matplotlib.org/stable/api/_as_gen/matplotlib.patches.Rectangle.html>`_.
Keyword arguments can be passed to the rectangle constructor thanks to the ``detection_rect_kwargs`` parameter:

.. code-block:: python

detection.plot(
ax=ax,
detection_rect_kwargs={ # Keyword arguments passed to the Rectangle constructor
"color": "#fde725",
"linewidth": 7,
},
)

# Show the spectrogram with the detection plotted on top of it
plt.show()

.. image::
_static/detections/detection_unlabelled.png
:align: center

Detection labels (:class:`osekit.core.detection.Label`) can be added to the detection rectangle thanks to the ``plot_label`` parameter.

# Plot the spectrogram
sd.plot(ax=ax)
Labels consist in a background `matplotlib Rectangle <https://matplotlib.org/stable/api/_as_gen/matplotlib.patches.Rectangle.html>`_ and a foreground
`matplotlib Text <https://matplotlib.org/stable/api/text_api.html#matplotlib.text.Text>`_.

# Get a rectangle from the detection
rectangle = detection.to_rectangle(fill = False)
Keyword arguments can be passed to the background rectangle thanks to the ``background_kwargs`` parameter and to the foreground text thanks to the
``text_kwargs`` parameter:

.. code-block:: python

# Draw the detection
ax.add_patch(rectangle)
detection.plot(
ax=ax,
detection_rect_kwargs={ # Keyword arguments passed to the detection Rectangle constructor
"color": "#fde725",
"linewidth": 7,
},
plot_label=True,
label_kwargs={
"anchor": "bottom_left",
"inner_text": True,
"text_kwargs": { # Keyword arguments passed to the label Text
"color": "#440154",
"size": "x-large"
},
"background_kwargs": {}, # Keyword arguments passed to the label background rectangle
},
)

# Show the spectrogram
plt.show()

.. image::
_static/detections/detection_labelled.png
:align: center

The label position (relative to the detection rectangle) can be set thanks to the ``anchor`` and ``inner_text`` parameters.

The following figure displays all 8 possible combinations. In the notation ``x_y_z``, ``x_y`` represents the anchor (``T_R`` stands for ``"top_right"``) and ``z`` represents the ``inner_text`` parameter (``I`` for ``True`` (inner), ``O`` for ``False`` (outer)).

.. image::
_static/detections/label_anchors.png
:align: center
3 changes: 3 additions & 0 deletions docs/source/detection.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ Detection
.. autoclass:: osekit.core.detection.Detection
:members:

.. autoclass:: osekit.core.detection.Label
:members:

.. autoclass:: osekit.core.detection.FrequencyBounds
:members:

Expand Down
91 changes: 52 additions & 39 deletions docs/source/example_aplose_result.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "initial_id",
"metadata": {
"collapsed": true,
"tags": [
"remove-cell"
]
},
"outputs": [],
"source": [
"# Executing this cell will:\n",
"\n",
Expand All @@ -21,9 +23,7 @@
"from osekit import setup_logging\n",
"\n",
"setup_logging() # Overwrites the default logger to"
],
"outputs": [],
"execution_count": null
]
},
{
"cell_type": "markdown",
Expand All @@ -36,8 +36,9 @@
]
},
{
"metadata": {},
"cell_type": "markdown",
"id": "90049102bdc38599",
"metadata": {},
"source": [
"# Creating the Public Project\n",
"\n",
Expand All @@ -46,22 +47,24 @@
"First, we will build a project and run a transform that would be uploaded and annotated on APLOSE (see the [Public API documentation](https://project-osmose.github.io/OSEkit/publicapi_usage.html) for more info).\n",
"\n",
"The `_static/detections/aplose_results.csv` file used in this notebook simulates the results of this annotation campaign."
],
"id": "90049102bdc38599"
]
},
{
"metadata": {},
"cell_type": "markdown",
"id": "e2d5321198880205",
"metadata": {},
"source": [
"## Build the Project\n",
"\n",
"First, we have to build the project from the raw audio files:"
],
"id": "e2d5321198880205"
]
},
{
"metadata": {},
"cell_type": "code",
"execution_count": null,
"id": "3ab3cb447c59a857",
"metadata": {},
"outputs": [],
"source": [
"from pathlib import Path\n",
"from osekit.public.project import Project\n",
Expand All @@ -78,24 +81,24 @@
")\n",
"\n",
"project.build()"
],
"id": "3ab3cb447c59a857",
"outputs": [],
"execution_count": null
]
},
{
"metadata": {},
"cell_type": "markdown",
"id": "2f5510c9c396ee2f",
"metadata": {},
"source": [
"## Declare & Run the Transform\n",
"\n",
"Then we **declare** and **run** a `Transform` which would export the spectrograms to be annotated:"
],
"id": "2f5510c9c396ee2f"
]
},
{
"metadata": {},
"cell_type": "code",
"execution_count": null,
"id": "d993991e8c23a2c0",
"metadata": {},
"outputs": [],
"source": [
"from osekit.public.transform import Transform, OutputType\n",
"from osekit.utils.audio import Normalization\n",
Expand All @@ -120,10 +123,7 @@
"ads.remove_empty_data(threshold=0.99)\n",
"\n",
"project.run(transform=transform, audio_dataset=ads)"
],
"id": "d993991e8c23a2c0",
"outputs": [],
"execution_count": null
]
},
{
"cell_type": "markdown",
Expand All @@ -133,16 +133,16 @@
},
{
"cell_type": "code",
"execution_count": null,
"id": "1948b260fcaf03ab",
"metadata": {},
"outputs": [],
"source": [
"from pathlib import Path\n",
"from osekit.core.detection import Detection\n",
"\n",
"detections = Detection.from_csv(csv=Path(r\"_static/detections/aplose_results.csv\"))"
],
"outputs": [],
"execution_count": null
]
},
{
"cell_type": "markdown",
Expand Down Expand Up @@ -171,8 +171,10 @@
},
{
"cell_type": "code",
"execution_count": null,
"id": "45892d179652235b",
"metadata": {},
"outputs": [],
"source": [
"def does_satisfy_constraints(detection: Detection) -> bool:\n",
" # Keeping only odontocete whistles\n",
Expand All @@ -196,9 +198,7 @@
"filtered_detections = [\n",
" detection for detection in detections if does_satisfy_constraints(detection)\n",
"]"
],
"outputs": [],
"execution_count": null
]
},
{
"cell_type": "markdown",
Expand All @@ -212,8 +212,10 @@
},
{
"cell_type": "code",
"execution_count": null,
"id": "237d399b7de6ffd5",
"metadata": {},
"outputs": [],
"source": [
"# Recover the transform output (SpectroDataset)\n",
"sds = project.get_output(output_name=\"example_transform\")\n",
Expand All @@ -224,9 +226,7 @@
" for sd in sds.data\n",
" if any(detection.overlaps(sd) for detection in filtered_detections)\n",
"]"
],
"outputs": [],
"execution_count": null
]
},
{
"cell_type": "markdown",
Expand All @@ -240,8 +240,10 @@
},
{
"cell_type": "code",
"execution_count": null,
"id": "d0d242240e791509",
"metadata": {},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt\n",
"\n",
Expand All @@ -261,25 +263,36 @@
" continue\n",
"\n",
" # Detections are plotted as matplotlib Rectangles\n",
" rectangle = detection.to_rectangle(fill=False)\n",
" ax.add_patch(rectangle)\n",
" detection.plot(\n",
" ax=ax,\n",
" plot_label=True, # We can plot the label along with the detection rectangle\n",
" detection_rect_kwargs={ # kwargs passed to the detection matplotlib Rectangle\n",
" \"color\": \"#fde725\"\n",
" },\n",
" label_kwargs={ # kwargs passed to the Label osekit object\n",
" \"anchor\": \"bottom_left\",\n",
" \"inner_text\": False,\n",
" \"background_kwargs\": {}, # kwargs passed to the label background matplotlib Rectangle\n",
" \"text_kwargs\": {\n",
" \"color\": \"#440154\"\n",
" }, # kwargs passed to the label matplotlib Text\n",
" },\n",
" )\n",
"\n",
"# Let's take a look at the output figure\n",
"plt.show()"
],
"outputs": [],
"execution_count": null
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "449dc442b4a5df75",
"metadata": {},
"outputs": [],
"source": [
"# Reset the project to get all files back to place.\n",
"project.reset()"
],
"outputs": [],
"execution_count": null
]
}
],
"metadata": {
Expand Down
Loading