Skip to content

bioamla.datasets

bioamla.datasets

Datasets domain: annotations + dataset operations.

This package folds the old services.dataset / services.annotation / core.annotations layers into plain, exception-raising functions with direct pathlib I/O.

It covers two related areas:

Annotations The :class:Annotation data structure, format conversion (Raven selection tables, CSV, JSON, Parquet), label engineering (label maps, one-hot/frame labels, remapping, filtering), clip extraction, and acoustic measurements.

Datasets Merging multiple audio datasets, audio augmentation, license/attribution generation, and metadata statistics.

Example

from bioamla.datasets import load_csv_annotations, save_raven_selection_table anns = load_csv_annotations("annotations.csv") save_raven_selection_table(anns, "selections.txt")

AnnotationSet dataclass

A collection of annotations for a single audio file.

Attributes:

Name Type Description
file_path str

Path to the associated audio file

annotations list[Annotation]

List of Annotation objects

sample_rate int | None

Sample rate of the audio file (optional)

duration float | None

Total duration of the audio file in seconds (optional)

metadata dict[str, Any]

Additional metadata about the file or annotation set

add

add(annotation: Annotation) -> None

Add an annotation to the set.

get_labels

get_labels() -> set[str]

Get all unique labels in this annotation set.

filter_by_label

filter_by_label(label: str) -> list[Annotation]

Get all annotations with a specific label.

filter_by_time_range

filter_by_time_range(
    start: float, end: float
) -> list[Annotation]

Get all annotations that overlap with a time range.

filter_by_freq_range

filter_by_freq_range(
    low: float, high: float
) -> list[Annotation]

Get all annotations that overlap with a frequency range.

sort_by_time

sort_by_time() -> None

Sort annotations by start time (in place).

merge_overlapping

merge_overlapping(
    same_label_only: bool = True,
) -> AnnotationSet

Merge overlapping annotations into a new :class:AnnotationSet.

Parameters:

Name Type Description Default
same_label_only bool

If True, only merge annotations with the same label.

True

Annotation dataclass

Represents a single time-frequency annotation.

Stores annotation data for a region of an audio file, defined by time boundaries and optional frequency boundaries.

Attributes:

Name Type Description
start_time float

Start time in seconds

end_time float

End time in seconds

low_freq float | None

Lower frequency bound in Hz (optional)

high_freq float | None

Upper frequency bound in Hz (optional)

label str

Primary label/class for the annotation

channel int

Audio channel (1-indexed, default 1)

confidence float | None

Confidence score (0.0-1.0, optional)

notes str

Additional notes or comments

custom_fields dict[str, Any]

Dictionary for storing custom annotation fields

duration property

duration: float

Get the duration of the annotation in seconds.

bandwidth property

bandwidth: float | None

Get the frequency bandwidth in Hz, or None if frequencies not set.

center_time property

center_time: float

Get the center time of the annotation.

center_freq property

center_freq: float | None

Get the center frequency, or None if frequencies not set.

overlaps_time

overlaps_time(other: Annotation) -> bool

Check if this annotation overlaps in time with another.

overlaps_freq

overlaps_freq(other: Annotation) -> bool

Check if this annotation overlaps in frequency with another.

overlaps

overlaps(other: Annotation) -> bool

Check if this annotation overlaps with another in time and frequency.

contains_time

contains_time(time: float) -> bool

Check if a time point falls within this annotation.

contains_freq

contains_freq(freq: float) -> bool

Check if a frequency falls within this annotation's bounds.

to_dict

to_dict() -> dict[str, Any]

Convert annotation to a dictionary.

from_dict classmethod

from_dict(data: dict[str, Any]) -> Annotation

Create an Annotation from a dictionary.

AnnotationResult dataclass

Result of annotation import operations (annotations + optional summary).

AugmentationConfig dataclass

Configuration for the audio augmentation pipeline.

DatasetManifest dataclass

Self-describing summary of a dataset directory.

AnnotationError

Bases: BioamlaError

An annotation operation (import/export/extraction/measurement) failed.

AugmentationError

Bases: DatasetError

Audio augmentation (noise/stretch/pitch/gain) failed.

DatasetError

Bases: BioamlaError

Base class for dataset-domain failures (merge, augment, license, stats).

LicenseGenerationError

Bases: DatasetError

Generating a license/attribution file from dataset metadata failed.

MergeError

Bases: DatasetError

Merging audio datasets failed.

annotations_to_one_hot

annotations_to_one_hot(
    annotations: list[Annotation],
    label_map: dict[str, int],
    num_classes: int | None = None,
) -> np.ndarray

Convert annotations to one-hot encoded labels.

Returns a numpy array of shape (num_annotations, num_classes).

create_label_map

create_label_map(labels: list[str]) -> dict[str, int]

Create a mapping from label strings to integer indices (sorted, unique).

filter_labels

filter_labels(
    annotations: list[Annotation],
    include_labels: set[str] | None = None,
    exclude_labels: set[str] | None = None,
) -> list[Annotation]

Filter annotations by include/exclude label sets.

generate_clip_labels

generate_clip_labels(
    annotations: list[Annotation],
    clip_start: float,
    clip_end: float,
    label_map: dict[str, int],
    min_overlap: float = 0.0,
    multi_label: bool = True,
) -> np.ndarray

Generate a label vector for a clip based on overlapping annotations.

Parameters:

Name Type Description Default
annotations list[Annotation]

List of annotations to check

required
clip_start float

Start time of the clip in seconds

required
clip_end float

End time of the clip in seconds

required
label_map dict[str, int]

Dictionary mapping labels to indices

required
min_overlap float

Minimum overlap ratio (0.0-1.0) required to assign a label

0.0
multi_label bool

If True, return multi-hot encoding; otherwise the single most-overlapping label wins.

True

Returns:

Type Description
ndarray

Label vector (one-hot or multi-hot encoded).

Raises:

Type Description
InvalidInputError

If clip_end <= clip_start.

generate_frame_labels

generate_frame_labels(
    annotations: list[Annotation],
    total_duration: float,
    frame_size: float,
    hop_length: float,
    label_map: dict[str, int],
) -> np.ndarray

Generate frame-level labels of shape (num_classes, num_frames).

Parameters:

Name Type Description Default
annotations list[Annotation]

List of annotations

required
total_duration float

Total audio duration in seconds

required
frame_size float

Frame size in seconds (must be positive)

required
hop_length float

Hop length in seconds (must be positive)

required
label_map dict[str, int]

Dictionary mapping labels to indices

required

Raises:

Type Description
InvalidInputError

If frame_size or hop_length is non-positive.

load_label_mapping

load_label_mapping(
    filepath: str, encoding: str = "utf-8"
) -> dict[str, str]

Load a label mapping (columns source, target) from a CSV file.

Raises:

Type Description
NotFoundError

If the file doesn't exist.

remap_labels

remap_labels(
    annotations: list[Annotation],
    label_mapping: dict[str, str],
    keep_unmapped: bool = True,
) -> list[Annotation]

Remap annotation labels using a mapping dictionary.

Parameters:

Name Type Description Default
annotations list[Annotation]

List of annotations to remap

required
label_mapping dict[str, str]

Dictionary mapping old labels to new labels

required
keep_unmapped bool

If True, keep annotations with unmapped labels unchanged; otherwise drop them.

True

Returns:

Type Description
list[Annotation]

New list of annotations with remapped labels.

save_label_mapping

save_label_mapping(
    mapping: dict[str, str],
    filepath: str,
    encoding: str = "utf-8",
) -> str

Save a label mapping to a CSV file with columns source, target.

create_annotation

create_annotation(
    start_time: float,
    end_time: float,
    label: str = "",
    low_freq: float | None = None,
    high_freq: float | None = None,
    channel: int = 1,
    confidence: float | None = None,
    notes: str = "",
) -> Annotation

Create a validated :class:Annotation.

Raises:

Type Description
AnnotationError

If end_time <= start_time or high_freq <= low_freq.

get_unique_labels

get_unique_labels(
    annotations: list[Annotation],
) -> list[str]

Get the sorted list of unique non-empty labels from annotations.

load_annotations_from_directory

load_annotations_from_directory(
    directory: str,
    file_pattern: str = "*.txt",
    format: str = "raven",
) -> dict[str, list[Annotation]]

Load annotations from all matching files in a directory.

Parameters:

Name Type Description Default
directory str

Path to directory containing annotation files

required
file_pattern str

Glob pattern for matching files

'*.txt'
format str

Annotation format ('raven' or 'csv')

'raven'

Returns:

Type Description
dict[str, list[Annotation]]

Dictionary mapping filename to list of annotations

Raises:

Type Description
NotFoundError

If the directory doesn't exist.

load_bioamla_annotations

load_bioamla_annotations(
    filepath: str,
) -> tuple[list[Annotation], dict[str, Any]]

Load annotations from a bioamla JSON format file.

Parameters:

Name Type Description Default
filepath str

Path to a .json file in the bioamla annotation format.

required

Returns:

Type Description
list[Annotation]

A (annotations, metadata) tuple, where metadata is the

dict[str, Any]

file-level header (audio_file, sample_rate, etc.) with the reserved

tuple[list[Annotation], dict[str, Any]]

format and annotations keys removed.

Raises:

Type Description
NotFoundError

If the file doesn't exist.

AnnotationError

If the file cannot be parsed or has the wrong shape.

load_csv_annotations

load_csv_annotations(
    filepath: str,
    start_time_col: str = "start_time",
    end_time_col: str = "end_time",
    low_freq_col: str = "low_freq",
    high_freq_col: str = "high_freq",
    label_col: str = "label",
    encoding: str = "utf-8",
) -> list[Annotation]

Load annotations from a CSV file with flexible column mapping.

Parameters:

Name Type Description Default
filepath str

Path to the CSV file

required
start_time_col str

Column name for start time

'start_time'
end_time_col str

Column name for end time

'end_time'
low_freq_col str

Column name for low frequency (optional in data)

'low_freq'
high_freq_col str

Column name for high frequency (optional in data)

'high_freq'
label_col str

Column name for label

'label'
encoding str

File encoding

'utf-8'

Returns:

Type Description
list[Annotation]

List of Annotation objects

Raises:

Type Description
NotFoundError

If the file doesn't exist.

AnnotationError

If the file cannot be parsed.

load_raven_selection_table

load_raven_selection_table(
    filepath: str,
    label_column: str | None = None,
    encoding: str = "utf-8",
) -> list[Annotation]

Load annotations from a Raven Pro selection table file.

Raven Pro exports tab-delimited text files with specific column headers. This function reads those files and converts them to Annotation objects.

Parameters:

Name Type Description Default
filepath str

Path to the Raven selection table file (.txt)

required
label_column str | None

Name of the column to use as label. If None, auto-detects from 'Annotation', 'Species', 'Label', or 'Class' columns.

None
encoding str

File encoding (default: utf-8)

'utf-8'

Returns:

Type Description
list[Annotation]

List of Annotation objects

Raises:

Type Description
NotFoundError

If the file doesn't exist.

AnnotationError

If the file cannot be parsed.

predictions_to_annotations

predictions_to_annotations(
    rows: Iterable[Mapping[str, Any]],
    *,
    min_confidence: float = 0.0,
    exclude_labels: Iterable[str] | None = None,
) -> list[Annotation]

Convert segment-level model predictions into Annotations for manual review.

Bridges model inference output — e.g. a segmented-prediction CSV from models ast predict --segment-duration (columns filepath/start/stop/prediction or .../start_time/end_time/...) — into editable :class:Annotation objects that a human can correct and then feed to dataset extract-clips. This closes the predict → review → dataset loop.

Recognizes both start/stop and start_time/end_time time keys, and prediction or label for the class. A source filename (filepath/file_name/source_file) is preserved in custom_fields['source_file'] when present.

Parameters:

Name Type Description Default
rows Iterable[Mapping[str, Any]]

Iterable of prediction rows (mappings); pass a DataFrame via df.to_dict("records").

required
min_confidence float

Drop predictions whose confidence is below this. Rows without a confidence value are always kept.

0.0
exclude_labels Iterable[str] | None

Labels to drop (e.g. a background/negative class).

None

Returns:

Name Type Description
One list[Annotation]

class:Annotation per kept prediction row.

save_bioamla_annotations

save_bioamla_annotations(
    annotations: list[Annotation],
    filepath: str,
    metadata: dict[str, Any] | None = None,
) -> str

Save annotations in the bioamla JSON format.

Unlike a flat CSV/Raven table, this format carries a file-level metadata header (e.g. audio_file, sample_rate, duration) alongside the annotation records, so an annotation file is self-describing and stays linked to the recording it describes.

Parameters:

Name Type Description Default
annotations list[Annotation]

List of Annotation objects.

required
filepath str

Output file path (.json).

required
metadata dict[str, Any] | None

Optional file-level metadata (audio_file, sample_rate, duration, channels, or any custom keys) merged into the header.

None

Returns:

Type Description
str

Path to the saved file.

Raises:

Type Description
AnnotationError

If the file cannot be written.

save_csv_annotations

save_csv_annotations(
    annotations: list[Annotation],
    filepath: str,
    include_custom_fields: bool = True,
    encoding: str = "utf-8",
) -> str

Save annotations to a CSV file.

Parameters:

Name Type Description Default
annotations list[Annotation]

List of Annotation objects

required
filepath str

Output file path

required
include_custom_fields bool

If True, include custom fields as additional columns

True
encoding str

File encoding

'utf-8'

Returns:

Type Description
str

Path to the saved file

Raises:

Type Description
AnnotationError

If the file cannot be written.

save_json_annotations

save_json_annotations(
    annotations: list[Annotation], filepath: str
) -> str

Save annotations to a JSON file (list of annotation dicts).

Parameters:

Name Type Description Default
annotations list[Annotation]

List of Annotation objects

required
filepath str

Output file path (.json)

required

Returns:

Type Description
str

Path to the saved file

Raises:

Type Description
AnnotationError

If the file cannot be written.

save_parquet_annotations

save_parquet_annotations(
    annotations: list[Annotation], filepath: str
) -> str

Save annotations to a Parquet file.

Parameters:

Name Type Description Default
annotations list[Annotation]

List of Annotation objects

required
filepath str

Output file path (.parquet)

required

Returns:

Type Description
str

Path to the saved file

Raises:

Type Description
AnnotationError

If the file cannot be written.

save_raven_selection_table

save_raven_selection_table(
    annotations: list[Annotation],
    filepath: str,
    include_custom_fields: bool = True,
    encoding: str = "utf-8",
) -> str

Save annotations to a Raven Pro selection table file.

Creates a tab-delimited text file compatible with Raven Pro software.

Parameters:

Name Type Description Default
annotations list[Annotation]

List of Annotation objects to save

required
filepath str

Output file path (.txt)

required
include_custom_fields bool

If True, include custom fields as additional columns

True
encoding str

File encoding (default: utf-8)

'utf-8'

Returns:

Type Description
str

Path to the saved file

Raises:

Type Description
AnnotationError

If the file cannot be written.

summarize_annotations

summarize_annotations(
    annotations: list[Annotation],
) -> dict[str, Any]

Generate summary statistics (counts, label histogram, durations).

augment_audio

augment_audio(
    audio: ndarray, sample_rate: int, pipeline: Any
) -> np.ndarray

Apply an augmentation pipeline to a 1-D float audio array.

Parameters:

Name Type Description Default
audio ndarray

Audio data as a numpy array.

required
sample_rate int

Sample rate of the audio.

required
pipeline Any

An audiomentations Compose pipeline.

required

Returns:

Type Description
ndarray

Augmented audio as a numpy array.

batch_augment

batch_augment(
    input_dir: str,
    output_dir: str,
    config: AugmentationConfig,
    recursive: bool = True,
    verbose: bool = True,
) -> dict[str, Any]

Augment all audio files in a directory.

Parameters:

Name Type Description Default
input_dir str

Directory containing audio files.

required
output_dir str

Directory for augmented output (created if missing).

required
config AugmentationConfig

Augmentation configuration.

required
recursive bool

Whether to search subdirectories.

True
verbose bool

Whether to print progress messages.

True

Returns:

Type Description
dict[str, Any]

Dict with keys files_processed, files_created, files_failed,

dict[str, Any]

and output_dir.

Raises:

Type Description
NotFoundError

If the input directory doesn't exist.

AugmentationError

If no augmentations are enabled.

create_augmentation_pipeline

create_augmentation_pipeline(
    config: AugmentationConfig,
) -> Any

Create an audiomentations Compose pipeline from a config.

This is the single builder shared by both augmentation use cases: synthetic dataset generation (dataset augment / :func:batch_augment, which leaves pipeline_probability=1.0 and shuffle=False) and on-the-fly training augmentation (models ast train, which enables gain_transition / clipping_distortion and sets a compose-level pipeline_probability with shuffle=True).

Returns:

Type Description
Any

A Compose pipeline, or None if no augmentations are enabled.

describe_augmentation_pipeline

describe_augmentation_pipeline(pipeline: Any) -> list[str]

Summarize each transform in an audiomentations Compose pipeline.

Introspects the built pipeline (rather than re-deriving from the config) so the description always reflects exactly what is applied — same source of truth as training. Each line is Name(p=...): k=v, ... for one transform.

Parameters:

Name Type Description Default
pipeline Any

A Compose pipeline from :func:create_augmentation_pipeline, or None.

required

Returns:

Type Description
list[str]

One description string per transform; empty list if pipeline is None.

batch_convert_annotations

batch_convert_annotations(
    input_dir: str,
    output_dir: str,
    to_format: str,
    from_format: str | None = None,
    recursive: bool = True,
    max_workers: int = 1,
    continue_on_error: bool = True,
    on_progress: Callable[[int, int], None] | None = None,
) -> BatchResult

Convert every annotation file in a directory to another format.

Parameters:

Name Type Description Default
input_dir str

Directory containing annotation files.

required
output_dir str

Directory for converted output (created per-file).

required
to_format str

Target format ('raven' or 'csv').

required
from_format str | None

Source format ('raven' or 'csv'); auto-detected if None.

None
recursive bool

Recurse into subdirectories.

True
max_workers int

Worker processes for parallel conversion.

1
continue_on_error bool

Keep going past per-file failures.

True
on_progress Callable[[int, int], None] | None

Optional (completed, total) progress callback.

None

Returns:

Name Type Description
A BatchResult

class:BatchResult summarizing the run.

Raises:

Type Description
InvalidInputError

If a format is invalid.

NotFoundError

If the input directory doesn't exist.

extract_audio_clips

extract_audio_clips(
    annotations: list[Annotation],
    audio_path: str,
    output_dir: str,
    padding_ms: float = 0.0,
    format: str = "wav",
    include_label_in_filename: bool = True,
    subdir_by_label: bool = False,
    bandpass: bool = False,
    target_sample_rate: int | None = None,
) -> dict[str, Any]

Extract one audio clip per annotation from a source audio file.

Parameters:

Name Type Description Default
annotations list[Annotation]

Annotations to extract.

required
audio_path str

Path to the source audio file.

required
output_dir str

Directory for output clips (created if missing).

required
padding_ms float

Padding in milliseconds added before/after each clip.

0.0
format str

Output audio file extension (wav, flac, ...).

'wav'
include_label_in_filename bool

Include the annotation label in the filename (ignored when subdir_by_label is set).

True
subdir_by_label bool

Place each clip in a <label>/ subdirectory (AudioFolder layout).

False
bandpass bool

When an annotation has both low_freq and high_freq, bandpass-filter the clip to that band.

False
target_sample_rate int | None

Resample each clip to this rate (e.g. 16000 for AST).

None

Returns:

Type Description
dict[str, Any]

Dict with total_clips, extracted_clips (list of paths),

dict[str, Any]

failed_clips (list of error strings), skipped_clips (annotations

dict[str, Any]

outside the audio), output_directory, and clips — a list of

dict[str, Any]

per-clip record dicts (file_name relative to output_dir, label,

dict[str, Any]

source_file, start_time, end_time, low_freq, high_freq, confidence,

dict[str, Any]

channel, sample_rate, duration).

Raises:

Type Description
NotFoundError

If the source audio file doesn't exist.

AnnotationError

If the audio file cannot be loaded.

extract_labeled_dataset

extract_labeled_dataset(
    source: str,
    output_dir: str,
    annotations: str | None = None,
    layout: str = "both",
    padding_ms: float = 0.0,
    bandpass: bool = False,
    format: str = "wav",
    target_sample_rate: int | None = None,
    include_labels: set[str] | None = None,
    exclude_labels: set[str] | None = None,
    min_duration: float | None = None,
    metadata_filename: str = "metadata.csv",
    source_metadata: str | None = None,
    verbose: bool = True,
) -> dict[str, Any]

Extract annotated regions into a labeled clip dataset.

Parameters:

Name Type Description Default
source str

An audio file, or a directory of audio files each paired with a sibling annotation file (same stem, .json/.txt/.csv).

required
output_dir str

Destination dataset directory (created if missing).

required
annotations str | None

Explicit annotation file when source is one audio file.

None
layout str

"both" (label subdirs + metadata.csv), "audiofolder" (label subdirs only), or "flat" (one dir + metadata.csv).

'both'
source_metadata str | None

Catalog metadata.csv to join license/attribution onto clips (by source-recording basename). Auto-detected as a metadata.csv sibling of source when omitted.

None
padding_ms float

Padding added before/after each clip.

0.0
bandpass bool

Bandpass-filter clips to each annotation's freq band when set.

False
format str

Output audio extension.

'wav'
target_sample_rate int | None

Resample clips to this rate (e.g. 16000 for AST).

None
include_labels set[str] | None

If set, keep only these labels.

None
exclude_labels set[str] | None

If set, drop these labels.

None
min_duration float | None

Drop annotations shorter than this (seconds).

None
metadata_filename str

Name of the metadata CSV written to output_dir.

'metadata.csv'
verbose bool

Log progress.

True

Returns:

Type Description
dict[str, Any]

Dict with clips_written, files_processed, labels (sorted),

dict[str, Any]

label_map, output_dir, metadata_file (or None), failed,

dict[str, Any]

skipped, and provenance (join summary: joined/matched/unmatched/

dict[str, Any]

source_metadata/columns).

Raises:

Type Description
NotFoundError

If the source path doesn't exist.

AnnotationError

If no usable audio/annotation pairs are found.

generate_license_for_dataset

generate_license_for_dataset(
    dataset_path: Path,
    template_path: Path | None = None,
    output_filename: str | None = None,
    metadata_filename: str = "metadata.csv",
    format: str = "text",
) -> dict[str, Any]

Generate a license/attribution file for a single dataset directory.

Parameters:

Name Type Description Default
dataset_path Path

Path to the dataset directory.

required
template_path Path | None

Optional template file to prepend.

None
output_filename str | None

Name for the output file. Defaults to LICENSE for format="text" and ATTRIBUTIONS.md for format="md".

None
metadata_filename str

Name of the metadata CSV file.

'metadata.csv'
format str

"text" (plain LICENSE) or "md" (Markdown ATTRIBUTIONS).

'text'

Returns:

Type Description
dict[str, Any]

Dict with output_path, file_size, attributions_count and

dict[str, Any]

dataset_path.

Raises:

Type Description
NotFoundError

If the metadata CSV is missing.

InvalidInputError

If the metadata is invalid or has no attributions.

LicenseGenerationError

If the file cannot be written.

generate_licenses_for_directory

generate_licenses_for_directory(
    audio_dir: Path,
    template_path: Path | None = None,
    output_filename: str | None = None,
    metadata_filename: str = "metadata.csv",
    format: str = "text",
) -> dict[str, Any]

Generate license files for every dataset subdirectory in a directory.

Parameters:

Name Type Description Default
audio_dir Path

Directory containing dataset subdirectories.

required
template_path Path | None

Optional template file to prepend.

None
output_filename str | None

Name for the output license files.

None
metadata_filename str

Name of the metadata CSV files.

'metadata.csv'

Returns:

Type Description
dict[str, Any]

Dict with datasets_found, datasets_processed, datasets_failed

dict[str, Any]

and a per-dataset results list.

Raises:

Type Description
NotFoundError

If the audio directory doesn't exist.

build_dataset_card

build_dataset_card(manifest: DatasetManifest) -> str

Render a HuggingFace dataset card (README.md) from a manifest.

Produces YAML front-matter (tags + task category) followed by a human-readable summary of classes, counts, splits, and source provenance.

build_manifest_from_metadata

build_manifest_from_metadata(
    dataset_dir: str,
    name: str = "",
    kind: str = "labeled",
    created: str = "",
    metadata_filename: str = "metadata.csv",
    sample_rate: int | None = None,
) -> DatasetManifest

Derive a :class:DatasetManifest from a dataset's metadata.csv.

The label vocabulary is built with :func:create_label_map so it matches the ordering AST training assigns (sorted, unique), keeping a manifest consistent with a trained model's config.label2id.

Raises:

Type Description
NotFoundError

If the metadata CSV is missing.

load_dataset_manifest

load_dataset_manifest(filepath: str) -> DatasetManifest

Load a manifest from a JSON file.

Raises:

Type Description
NotFoundError

If the file doesn't exist.

DatasetError

If the file cannot be parsed.

save_dataset_manifest

save_dataset_manifest(
    manifest: DatasetManifest, filepath: str
) -> str

Write a manifest to a JSON file.

Raises:

Type Description
DatasetError

If the file cannot be written.

write_dataset_card

write_dataset_card(
    dataset_dir: str,
    metadata_filename: str = "metadata.csv",
    output_filename: str = "README.md",
) -> str | None

Write a HuggingFace dataset card (README.md) for a dataset directory.

Uses an existing dataset.json manifest if present, otherwise derives one from the metadata CSV. Returns the card path, or None when the directory has neither a manifest nor a metadata CSV to build from (so the caller can treat a non-dataset folder as a no-op).

compute_measurements

compute_measurements(
    annotation: Annotation,
    audio_path: str,
    metrics: list[str] | str | None = None,
) -> dict[str, float]

Compute acoustic measurements for one annotation region.

Parameters:

Name Type Description Default
annotation Annotation

The annotation to measure.

required
audio_path str

Path to the source audio file.

required
metrics list[str] | str | None

Metrics to compute. None uses :data:DEFAULT_METRICS; the string "all" expands to :data:ALL_METRICS; otherwise pass a list of metric names. Supported names, grouped by domain:

  • time: duration, zero_crossing_rate (crossings per sample, 0–1), peak_time (s from region start)
  • amplitude: rms, peak (linear), crest_factor (linear peak/rms), rms_db, peak_db (dBFS), crest_factor_db (dB), dynamic_range (dB)
  • power: avg_power, max_power, energy (Σ x²)
  • frequency (band-limited Welch PSD): bandwidth (annotation box width), centroid, bandwidth_spectral, rolloff (85%), peak_frequency, freq_q1/freq_q3 (25/75%), freq_5/freq_95 (5/95%), bandwidth_90 (95−5%), bandwidth_iqr (75−25%)
  • entropy: spectral_entropy, temporal_entropy
  • peak-frequency contour: pfc_min, pfc_max, pfc_mean, pfc_start, pfc_end, pfc_slope (Hz/s)
None

Returns:

Type Description
dict[str, float]

Dict mapping metric name to value. Metrics that cannot be computed for

dict[str, float]

the region are omitted.

Raises:

Type Description
NotFoundError

If the audio file doesn't exist.

AnnotationError

If metrics is malformed, or the audio cannot be loaded or measured.

find_species_name

find_species_name(
    category: str, all_categories: set[str]
) -> str

Return the most general matching species name for a (sub)species category.

If category is a subspecies (e.g. "Genus species subsp"), return the shortest known category that is a strict prefix of it; otherwise return category unchanged.

merge_datasets

merge_datasets(
    dataset_paths: list[str],
    output_dir: str,
    metadata_filename: str = "metadata.csv",
    skip_existing: bool = True,
    organize_by_category: bool = True,
    target_format: str | None = None,
    verbose: bool = True,
) -> dict[str, Any]

Merge multiple audio datasets into a single output dataset.

Combines audio files and metadata from several dataset directories into one output directory, optionally organizing by category and converting formats.

Parameters:

Name Type Description Default
dataset_paths list[str]

Paths to dataset directories to merge.

required
output_dir str

Output directory for the merged dataset.

required
metadata_filename str

Name of the metadata CSV in each dataset.

'metadata.csv'
skip_existing bool

Skip files that already exist in the output.

True
organize_by_category bool

Organize files into per-category subdirectories.

True
target_format str | None

Convert all audio to this format during merge.

None
verbose bool

Print progress information.

True

Returns:

Type Description
dict[str, Any]

Dict of summary stats: datasets_merged, total_files,

dict[str, Any]

files_copied, files_skipped, files_converted, output_dir,

dict[str, Any]

metadata_file.

Raises:

Type Description
InvalidInputError

If no paths given or target_format is unsupported.

NotFoundError

If a source dataset path does not exist.

MergeError

If reading/writing metadata fails.

partition_dataset

partition_dataset(
    dataset_dir: str,
    splits: tuple[float, float, float] = (0.7, 0.15, 0.15),
    seed: int = 0,
    stratify: bool = True,
    mode: str = "subdirs",
    group_by: str | None = "source_file",
    background_label: str | None = None,
    metadata_filename: str = "metadata.csv",
    verbose: bool = True,
) -> dict[str, Any]

Partition a dataset into train/val/test.

Parameters:

Name Type Description Default
dataset_dir str

Dataset directory containing metadata.csv.

required
splits tuple[float, float, float]

(train, val, test) fractions; must sum to 1.0 (val may be 0).

(0.7, 0.15, 0.15)
seed int

Reproducible shuffle seed.

0
stratify bool

Balance each label across splits.

True
mode str

"subdirs" (reorganize into train/val/test/<label>/) or "column" (populate the split column in place).

'subdirs'
group_by str | None

Column whose value keeps rows together in one split (default source_file — prevents clip leakage). Falls back to per-row when the column is absent.

'source_file'
background_label str | None

If set, this label is partitioned as its own stratum so it appears in every split even when sparse.

None
metadata_filename str

Name of the metadata CSV.

'metadata.csv'
verbose bool

Log progress.

True

Returns:

Type Description
dict[str, Any]

Dict with splits (split->count), groups, mode,

dict[str, Any]

metadata_file, dataset_dir.

Raises:

Type Description
NotFoundError

If the metadata CSV is missing.

DatasetError

On bad arguments or empty metadata.

get_dataset_stats

get_dataset_stats(
    dataset_path: str,
    metadata_filename: str = "metadata.csv",
) -> dict[str, Any]

Compute statistics for a dataset from its metadata CSV.

Parameters:

Name Type Description Default
dataset_path str

Path to the dataset directory.

required
metadata_filename str

Name of the metadata CSV file.

'metadata.csv'

Returns:

Type Description
dict[str, Any]

Dict with total_files, categories (label->count), licenses

dict[str, Any]

(license->count), splits (split->count), num_categories and

dict[str, Any]

num_licenses.

Raises:

Type Description
NotFoundError

If the metadata CSV is missing.

DatasetError

If the metadata cannot be read.