Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
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
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
32 changes: 32 additions & 0 deletions docs/source/coreapi_usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,38 @@ This is the default behaviour, but other ways of computing the ``AudioData`` tim
You don't have to worry about the shape of the original audio files: audio data will be fetched seamlessly in the corresponding
file(s) whenever you need it.

Non-timestamped audio files
"""""""""""""""""""""""""""

In case you don't know the timestamps at which your audio files were recorded (or you don't care specifying them), you can specify
a default timestamp at which the first valid audio file in the folder will be considered to start thanks to the
``first_file_begin`` parameter.

Each next valid audio file will be considered to start immediately after the end of the previous one.

.. code-block:: python

from pathlib import Path
from osekit.core_api.audio_dataset import AudioDataset
from osekit.core_api.instrument import Instrument
from pandas import Timestamp, Timedelta

folder = Path(r"...")
ads = AudioDataset.from_folder
(
folder=folder,
strptime_format=None # Will use first_file_begin to timestamp the files
first_file_begin=Timestamp("2009-01-06 10:00:00"),
begin=Timestamp("2009-01-06 12:00:00"), # We can still specify the begin/end timestamps of the required dataset
end=Timestamp("2009-01-06 14:00:00"),
data_duration=Timedelta("10s"),
instrument=Instrument(end_to_end_db=150),
normalization="dc_reject"
)

In the example above, the first valid file in the folder will be considered to start at ``2009-01-06 10:00:00``.
If this first file is 1 hour-long, the next one will be considered to start at ``2009-01-06 11:00:00``, and so on.

Manipulation
""""""""""""

Expand Down
2 changes: 1 addition & 1 deletion docs/source/example_ltas_core.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
"source": [
"from pathlib import Path\n",
"\n",
"audio_folder = Path(r\"_static/sample_audio\")\n",
"audio_folder = Path(r\"_static/sample_audio/timestamped\")\n",
"\n",
"from osekit.core_api.audio_dataset import AudioDataset\n",
"from osekit.utils.audio_utils import Normalization\n",
Expand Down
2 changes: 1 addition & 1 deletion docs/source/example_ltas_public.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
"source": [
"from pathlib import Path\n",
"\n",
"audio_folder = Path(r\"_static/sample_audio\")\n",
"audio_folder = Path(r\"_static/sample_audio/timestamped\")\n",
"\n",
"from osekit.public_api.dataset import Dataset\n",
"from osekit.core_api.instrument import Instrument\n",
Expand Down
4 changes: 2 additions & 2 deletions docs/source/example_multiple_spectrograms.rst
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Computing multiple spectrograms
===============================
Computing multiple spectrograms (timestamped files)
===================================================

.. _example_multiple_spectrograms:

Expand Down
2 changes: 1 addition & 1 deletion docs/source/example_multiple_spectrograms_core.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
"source": [
"from pathlib import Path\n",
"\n",
"audio_folder = Path(r\"_static/sample_audio\")\n",
"audio_folder = Path(r\"_static/sample_audio/timestamped\")\n",
"\n",
"from osekit.core_api.audio_dataset import AudioDataset\n",
"from osekit.core_api.instrument import Instrument\n",
Expand Down
20 changes: 20 additions & 0 deletions docs/source/example_multiple_spectrograms_id.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Computing multiple spectrograms (ID files)
==========================================

.. _example_multiple_spectrograms_id:

In this example, we want to export spectrograms drawn from the sample audio dataset with the following requirements:

* Start timestamps of the audio files are unknown
* One single ``8 s``-long spectrogram should be exported per audio file
* Audio data are downsampled sampled at ``24 kHz`` before spectrograms are computed
* The DC component of the audio data is rejected before spectrograms are computed
* Exported spectrogram images should be named after the audio file IDs

The FFT used for computing the spectrograms will use a ``1024 samples``-long hamming window, with a ``128 samples``-long hop.

.. toctree::
:maxdepth: 1

example_multiple_spectrograms_id_core
example_multiple_spectrograms_id_public
257 changes: 257 additions & 0 deletions docs/source/example_multiple_spectrograms_id_core.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,257 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"id": "dc7ebca70b3b5da",
"metadata": {
"tags": [
"remove-cell"
]
},
"outputs": [],
"source": [
"# Executing this cell will disable all TQDM outputs in stdout.\n",
"import os\n",
"\n",
"os.environ[\"DISABLE_TQDM\"] = \"True\""
]
},
{
"cell_type": "markdown",
"id": "5d67c1697ae837a4",
"metadata": {},
"source": [
"# Computing multiple spectrograms with the Core API [^download]\n",
"\n",
"[^download]: This notebook can be downloaded as **{nb-download}`example_multiple_spectrograms_id_core.ipynb`**."
]
},
{
"cell_type": "markdown",
"id": "66731c408df9271c",
"metadata": {},
"source": [
"Create an **OSEkit** `AudioDataset` from the files on disk, by directly specifying the requirements in the constructor.\n",
"\n",
"Since we don't know (nor we care about) the files begin timestamps, we'll set the `striptime_format` to `None`, which will assign a default timestamp at which the first valid audio file will be considered to start. Then, each next valid audio file will be considered as starting at the end of the previous one. This default timestamp can be editted thanks to the `first_file_begin` parameter.\n",
"\n",
"An `Instrument` can be provided to the `AudioDataset` for the audio data to be converted in pressure units. This will lead the resulting spectra to be expressed in dB SPL (rather than in dB FS):\n",
"\n",
"We will only use the **folder** in which the files are located: we don't have to dig up to the file level."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "2f36ef512e49e57b",
"metadata": {},
"outputs": [],
"source": [
"from pathlib import Path\n",
"\n",
"audio_folder = Path(r\"_static/sample_audio/id\")\n",
"\n",
"from osekit.core_api.audio_dataset import AudioDataset\n",
"from osekit.core_api.instrument import Instrument\n",
"from osekit.utils.audio_utils import Normalization\n",
"\n",
"audio_dataset = AudioDataset.from_folder(\n",
" folder=audio_folder,\n",
" strptime_format=None,\n",
" mode=\"files\", # Will create one audio data per file. We'll trim them later\n",
" instrument=Instrument(end_to_end_db=165.0),\n",
" sample_rate=24_000,\n",
" normalization=Normalization.DC_REJECT,\n",
")"
]
},
{
"cell_type": "markdown",
"id": "ae4f34cb1e7707e5",
"metadata": {},
"source": "The `AudioDataset` object contains all the to-be-exported `AudioData`:"
},
{
"cell_type": "code",
"execution_count": null,
"id": "7b81ebdba07f5ccf",
"metadata": {},
"outputs": [],
"source": [
"print(f\"{' AUDIO DATASET ':#^60}\")\n",
"print(f\"{'Begin:':<30}{str(audio_dataset.begin):>30}\")\n",
"print(f\"{'End:':<30}{str(audio_dataset.end):>30}\")\n",
"print(f\"{'Sample rate:':<30}{str(audio_dataset.sample_rate):>30}\")\n",
"print(f\"{'Nb of audio data:':<30}{str(len(audio_dataset.data)):>30}\")"
]
},
{
"cell_type": "markdown",
"id": "eeafddd2f84557ac",
"metadata": {},
"source": "We want to trim these audio data so that they all last `8 s`:"
},
{
"cell_type": "code",
"execution_count": null,
"id": "ce629441ea840976",
"metadata": {},
"outputs": [],
"source": [
"from pandas import Timedelta\n",
"\n",
"for ad in audio_dataset.data:\n",
" ad.end = ad.begin + Timedelta(seconds=8)"
]
},
{
"cell_type": "markdown",
"id": "ff463689d799a823",
"metadata": {},
"source": "Now, we instantiate a `scipy.signal.ShortTimeFFT` FFT object with the required parameters:"
},
{
"cell_type": "code",
"execution_count": null,
"id": "a5c030c6cf06128",
"metadata": {
"tags": []
},
"outputs": [],
"source": [
"from scipy.signal import ShortTimeFFT\n",
"from scipy.signal.windows import hamming\n",
"\n",
"sft = ShortTimeFFT(\n",
" win=hamming(1024),\n",
" hop=128,\n",
" fs=audio_dataset.sample_rate,\n",
")"
]
},
{
"cell_type": "markdown",
"id": "946ef52ed70d0642",
"metadata": {},
"source": [
"Create an **OSEkit** `SpectroDataset` from the `AudioDataset` and the `ShortTimeFFT` objects.\n",
"\n",
"We'll also rename these spectro data so that the exported files are named after the original audio file names (that are the IDs)."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7397ac200756cd82",
"metadata": {},
"outputs": [],
"source": [
"from osekit.core_api.spectro_dataset import SpectroDataset\n",
"\n",
"spectro_dataset = SpectroDataset.from_audio_dataset(\n",
" audio_dataset=audio_dataset,\n",
" fft=sft,\n",
" v_lim=(0.0, 150.0), # Boundaries of the spectrograms\n",
" colormap=\"viridis\", # Default value\n",
")\n",
"\n",
"# RENAMING\n",
"for sd in spectro_dataset.data:\n",
" sd.name = next(iter(sd.audio_data.files)).path.stem"
]
},
{
"cell_type": "markdown",
"id": "b3fd3bd205bc369c",
"metadata": {},
"source": "We can plot sample `SpectroData` object(s) if we want to glance at the output before computing all spectrograms (notice the 25% overlap as specified):"
},
{
"cell_type": "code",
"execution_count": null,
"id": "e42dfe3608c8b59e",
"metadata": {},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt\n",
"\n",
"fig, axs = plt.subplots(2, 1)\n",
"\n",
"spectro_dataset.data[0].plot(ax=axs[1])\n",
"spectro_dataset.data[1].plot(ax=axs[0])\n",
"axs[0].get_xaxis().set_visible(False)\n",
"plt.show()"
]
},
{
"cell_type": "markdown",
"id": "cb64ef0bb8d69218",
"metadata": {},
"source": "We are now ready to export the spectrograms and matrices:"
},
{
"cell_type": "code",
"execution_count": null,
"id": "c28a40fe9093dfeb",
"metadata": {
"tags": [
"skip-execution"
]
},
"outputs": [],
"source": [
"# Export all spectrograms\n",
"spectro_dataset.save_spectrogram(folder=audio_folder / \"spectrograms\")\n",
"\n",
"# Export all NPZ matrices\n",
"spectro_dataset.write(folder=audio_folder / \"matrices\")"
]
},
{
"cell_type": "markdown",
"id": "b6d50da7dfb1dffc",
"metadata": {},
"source": [
"## PSD estimates\n",
"\n",
"We can also export Power Spectral Density estimates using the welch method:"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "4829920bbacee0b2",
"metadata": {
"tags": [
"skip-execution"
]
},
"outputs": [],
"source": [
"spectro_dataset.write_welch(folder=audio_folder / \"welch\")"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.6"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Loading