Source code for pykanto.parameters

# ─── DESCRIPTION ──────────────────────────────────────────────────────────────

"""
Classes and methods to store and modify pykanto parameters.
"""

# ──── IMPORTS ─────────────────────────────────────────────────────────────────
from __future__ import annotations
import json
from typing import Any, Tuple
import attr
from pykanto.utils.compute import print_dict

# ──── CLASSES AND METHODS ─────────────────────────────────────────────────────


[docs]class Parameters: # TODO: #8 Parameters should be an attrs class with validation @nilomr """ General parameters class - stores parameters to be passed to a :meth:`~pykanto.dataset.KantoData` object. """
[docs] def __init__(self, **kwargs: Any): """ Sets default parameters, then updates with user-provided parameters. """ # Set defaults first # Spectrogramming self.window_length: int = 1024 """Number of samples. Defaults to 1024.""" self.hop_length: int = 128 """Number of samples between successive frames. Defaults to 128.""" self.fft_size: int = 2048 """Number of bins used to divide the window. Defaults to 2048.""" self.num_mel_bins: int = 224 """Number of Mel frequency bins to use (n of 'rows' in mel-spectrogram). Defaults to 224.""" self.sr: int = 22050 """The sampling rate (samples taken per second). Defaults to 22050.""" self.hop_length_ms: float = self.sr / self.hop_length """Calculated automatically.""" self.fft_rate: float = 1000 / self.hop_length_ms """Calculated automatically.""" self.top_dB: int = 65 """Top dB to keep. Defaults to 65. Example: if ``top_dB`` = 65 anything below -65dB will be masked.""" self.lowcut: int = 1000 """Minimum frequency (in Hz) to include by default. Defaults to 1000.""" self.highcut: int = 10000 """Maximum frequency (in Hz) to include by default. Defaults to 10000.""" self.dereverb: bool = False """Wether to reduce reverberation in the spectrograms. Defaults to False""" # Segmentation self.max_dB: int = -30 """Maximum threshold to reach during segmentation, in dB. Defaults to -30""" self.dB_delta: int = 5 """Size of thresholding steps, in dB. Defaults to 5.""" self.silence_threshold: float = 0.2 """Threshold separating silence from voiced segments. Between 0.1 and 0.3 tends to work well. Defaults to 0.2.""" self.max_unit_length: float = 0.4 """Maximum unit length allowed. Defaults to 0.4. """ self.min_unit_length: float = 0.03 """Minimum unit length allowed. Defaults to 0.03.""" self.min_silence_length: float = 0.001 """Minimum silence length allowed. Defaults to 0.001.""" self.gauss_sigma: int = 3 """Sigma for gaussian kernel. Defaults to 3.""" # general settings self.song_level: bool = False """Whether to return the average of all units. Defaults to False (return individual units in each vocalisation)""" self.subset: Tuple[int, int] | None = None """Indices of the first and last items to include in the dataset. Optional, defaults to None.""" self.num_cpus: None | int = None """How many cpus to use for parallel computing. Default is available number of cpus""" self.verbose: bool = False """How much detail to provide. Defaults to False (not verbose).""" # Update with user-provided parameters. self.__dict__.update(kwargs)
[docs] def update(self, **kwargs: Any) -> None: """ Update one or more parameters. Raises: KeyError: Not a valid parameter name. """ for key, val in kwargs.items(): if key not in self.__dict__: raise KeyError( f"'{key}'' is not an existing parameter." f"Use `.add({key} = {val})` instead f you want to add a new parameter." ) self.__dict__.update(kwargs)
[docs] def add(self, **kwargs: Any) -> None: """ Add one or more new parameters. """ self.__dict__.update(kwargs)
def __str__(self) -> str: """ Returns the class objects as a string. Returns: str: Pretty printed dictionary contents. """ return print_dict(self.__dict__)