Package

Primary public entry points. Individual feature callables are documented under Feature definitions (and summarised in the interactive Feature catalogue). They are also importable from this package root.

Batch extraction

get_all_features(input, config=None, log_level=20, skip_idyom=False, long_format=False, join_metadata=True)[source]

Calculate a multitude of features from across the computational melody analysis field. This function returns a pandas DataFrame with a row for every melody in the supplied input.

The input can be: - A directory path containing MIDI files - A list of MIDI file paths - A single MIDI file path - A list of Melody objects

If a path to a corpus of MIDI files is provided in the Config, corpus statistics will be computed following FANTASTIC’s n-gram document frequency model (Müllensiefen, 2009). If not, this will be skipped. This function will also run IDyOM (Pearce, 2005) on the input MIDI files. If a corpus of MIDI files is provided in the Config, IDyOM will be run with pretraining on the corpus. If not, it will be run without pretraining.

Parameters:
  • input (FeatureInput) – Path to input MIDI directory, list of MIDI file paths, single MIDI file path, or list of in-memory Melody objects

  • config (Config) – Configuration object containing corpus path, IDyOM configurations (as a dict), and FANTASTIC configuration. If idyom.corpus or fantastic.corpus is set, those take precedence over config.corpus for their respective methods. If multiple IDyOM configs are provided, IDyOM will run for each config and features for each will be included with an identifier in the output.

  • log_level (int) – Logging level (default: logging.INFO)

  • skip_idyom (bool) – If True, skip IDyOM feature calculation (default: False)

  • long_format (bool) – If True, return a tidy long-format DataFrame (one row per melody/feature combination, with feature_name and value columns) instead of the default wide format. See melody_features.to_long_format(), which can also be applied to an existing wide DataFrame (default: False)

  • join_metadata (bool) – Only used when long_format=True. If True, join feature metadata (family, source, domain, type, description, notes, references) onto the long DataFrame by feature_name, so features can be filtered or grouped by source/family without a separate join step. See melody_features.get_feature_metadata() (default: True)

Returns:

A pandas DataFrame with a row for every melody in the input, containing all extracted features. You can save this to CSV using df.to_csv(‘filename.csv’) if needed. If long_format=True, one row per melody/feature combination instead. Returns None if no valid melodies are loaded. If melodies load but no features are extracted, an empty DataFrame is returned.

Return type:

pd.DataFrame or None

list_available_features(*, domain=None, feature_type=None, source=None, detailed=False, module=None)[source]

List atomic features available in the package.

Parameters:
  • domain (str, optional) – Filter by feature domain (pitch, rhythm, or both)

  • feature_type (str, optional) – Filter by decorator type (e.g. absolute, interval, contour)

  • source (str, optional) – Filter by implementation source (e.g. fantastic, jsymbolic)

  • detailed (bool, optional) – If True, return metadata dictionaries instead of names only

  • module (module, optional) – Module to scan (defaults to melody_features.features)

Returns:

Feature names, or metadata records when detailed=True

Return type:

list[str] or list[dict]

get_feature_metadata()[source]

Return a metadata table for every feature produced by get_all_features.

One row per feature family.feature_name combination (matching the dotted column names in the wide-format DataFrame returned by melody_features.get_all_features()), with columns describing the feature’s source, family/category, domain, return type, and description. This table can be joined onto a long-format feature table by feature_name (see melody_features.to_long_format()).

to_long_format falls back to inferring family/source from the column prefix for any wide-format column (e.g. dynamic IDyOM columns) that doesn’t have an exact match here.

Returns:

Columns: feature_name, family, source, domain, type, description, notes, references.

Return type:

pd.DataFrame

to_long_format(df, *, join_metadata=True, metadata=None)[source]

Reshape a wide-format feature DataFrame into tidy long format.

Parameters:
  • df (pd.DataFrame) – A wide-format DataFrame as returned by get_all_features, with melody_num/melody_id identifier columns and one {family}.{feature} column per feature.

  • join_metadata (bool, optional) – If True (default), left-join feature metadata (family, source, domain, type, description, notes, references) onto the long DataFrame by feature_name. Any feature_name without an exact metadata match (chiefly dynamic IDyOM columns) falls back to a family/source inferred from the column prefix rather than being left blank.

  • metadata (pd.DataFrame, optional) – A metadata table to join instead of the default melody_features.get_feature_metadata() table (for example, a filtered or user-extended version). Must contain a feature_name column plus any of the columns in family, source, domain, type, description, notes, references.

Returns:

Columns: melody_num, melody_id, feature_name, value, and (when join_metadata=True) family, source, domain, type, description, notes, references.

Return type:

pd.DataFrame

Configuration

class Config(idyom, fantastic, corpus=None, key_estimation='infer_if_necessary', key_finding_algorithm='krumhansl_schmuckler')[source]

Bases: object

Configuration for get_all_features().

Use Config to control corpus statistics, FANTASTIC settings, key estimation, and IDyOM. The idyom field is a non-empty dictionary of named IDyOMConfig objects: each entry runs IDyOM once, and the dict key labels that run in the output columns. That lets you compare several IDyOM setups (models, viewpoints, corpora) in a single feature-extraction call.

Parameters:
  • idyom (dict[str, melody_features.idyom.config.IDyOMConfig]) – Mapping of run label → IDyOMConfig. Must contain at least one entry.

  • fantastic (melody_features.pipeline.config.FantasticConfig) – FantasticConfig for corpus n-gram features.

  • corpus (os.PathLike | None) – Optional default reference corpus path (FANTASTIC / IDyOM LTM). Per-entry IDyOMConfig.corpus and FantasticConfig.corpus override this when set.

  • key_estimation (Literal['always_read_from_file', 'infer_if_necessary', 'always_infer']) – "always_read_from_file", "infer_if_necessary" (default), or "always_infer".

  • key_finding_algorithm (Literal['krumhansl_schmuckler']) – Currently only "krumhansl_schmuckler".

idyom: dict[str, IDyOMConfig]
fantastic: FantasticConfig
corpus: PathLike | None = None
key_estimation: Literal['always_read_from_file', 'infer_if_necessary', 'always_infer'] = 'infer_if_necessary'
key_finding_algorithm: Literal['krumhansl_schmuckler'] = 'krumhansl_schmuckler'
class FantasticConfig(max_ngram_order, phrase_gap, corpus=None)[source]

Bases: object

Settings for FANTASTIC-style features (tokenization and corpus n-grams).

These options apply to lexical-diversity / m-type features and to corpus-relative FANTASTIC statistics computed by get_all_features().

Parameters:
  • max_ngram_order (int) – Inclusive maximum n-gram / m-type length (must be >= 1). Features use orders 1 through this value (FANTASTIC default range is 1–5).

  • phrase_gap (float) – Inter-onset interval threshold in quarter-note units (must be > 0). An IOI larger than this starts a new phrase when the melody is segmented for tokenization.

  • corpus (os.PathLike | None) – Optional MIDI directory for FANTASTIC corpus statistics. If None, the parent Config corpus is used. Independent of IDyOM pretraining corpora.

max_ngram_order: int
phrase_gap: float
corpus: PathLike | None = None
class IDyOMConfig(target_viewpoints, source_viewpoints, ppm_order, models, corpus=None)[source]

Bases: object

Settings for a single IDyOM run.

Place one or more instances in the idyom dict of Config (dict keys label the runs in the output). Each entry is executed separately.

Parameters:
  • target_viewpoints (list[str | tuple[str, ...]]) – Viewpoints to predict (e.g. ["cpitch"]). Entries are atomic viewpoint name strings from VALID_VIEWPOINTS.

  • source_viewpoints (list[str | tuple[str, ...]]) – Conditioning viewpoints. Use strings for atomic viewpoints, and tuples (parentheses) of two or more atoms for linked viewpoints, e.g. [("cpint", "cpintfref"), "cpcint"]. Strings and tuples may be mixed in one list.

  • ppm_order (int) – PPM model order.

  • models (str) – ":stm", ":ltm", or ":both".

  • corpus (os.PathLike | None) – Optional pretraining corpus for long-term models. Must be None when models=":stm". If None for :ltm / :both, the parent Config corpus is used when needed.

target_viewpoints: list[str | tuple[str, ...]]
source_viewpoints: list[str | tuple[str, ...]]
ppm_order: int
models: str
corpus: PathLike | None = None

Corpora helpers

get_corpus_path(corpus_name)[source]

Get the path to a bundled corpus.

Parameters:

corpus_name (str) – Name of the corpus. Currently supports: ‘essen’, ‘pearce_default_idyom’.

Returns:

Path to the corpus directory

Return type:

Path

Raises:
get_corpus_files(corpus_name, max_files=None)[source]

Get a list of MIDI files from a bundled corpus.

Parameters:
  • corpus_name (str) – Name of the corpus. Currently supports: ‘essen’, ‘pearce_default_idyom’.

  • max_files (int, optional) – Maximum number of files to return. If None, returns all files.

Returns:

List of MIDI file paths

Return type:

List[Path]

Raises:
list_available_corpora()[source]

List all available bundled corpora.

Returns:

List of available corpus names

Return type:

List[str]

load_melodies_from_directory(directory, file_type='json', njobs=-1)[source]

Load melodies from a directory containing either JSON or MIDI files.

Parameters:
  • directory (str) – Path to directory containing melody files

  • file_type (str) – Type of files to load (“json” or “midi”)

  • njobs (int | None)

Returns:

List of loaded melody objects

Return type:

List[Melody]