Module music_df.conversions.ms3

A function, ms3_to_df(), for converting ms3 dfs to the format used by this package.

Functions

def ms3_to_df(ms3_df: pandas.DataFrame,
measures_df: pandas.DataFrame | None,
remove_zero_duration_notes: bool = True,
drop_first_endings: bool = True,
fractions: bool = True,
drop_unused_cols: bool = True) ‑> pandas.DataFrame
Expand source code
def ms3_to_df(
    ms3_df: pd.DataFrame,
    measures_df: pd.DataFrame | None,
    remove_zero_duration_notes: bool = True,
    drop_first_endings: bool = True,
    fractions: bool = True,
    drop_unused_cols: bool = True,
) -> pd.DataFrame:
    """
    Convert an ms3 dataframe to the format used by this package.
    """
    out_df = ms3_df.copy()
    if "quarterbeats_playthrough" in out_df.columns:
        # This means the repeats are expanded
        pass
    elif drop_first_endings:
        out_df = out_df[~out_df["quarterbeats"].isna()].reset_index(drop=True)
        if measures_df is not None:
            if "quarterbeats" in measures_df.columns:
                measures_df = measures_df[
                    ~measures_df["quarterbeats"].isna()
                ].reset_index(drop=True)
    else:
        raise NotImplementedError

    _handle_times(out_df, fractions)

    if "name" in out_df.columns:
        # remove last character of "name" column (A4 -> A, etc.)
        out_df["spelling"] = out_df["name"].str[:-1]
    else:
        # earlier versions of ms3 don't seem to have the name column but
        #   we can get the spelling from the "tpc" column
        out_df["spelling"] = out_df["tpc"].apply(tpc2name)

    # rename some columns
    out_df.rename(columns={"midi": "pitch", "staff": "part"}, inplace=True)

    # add "tie_to_next" boolean column true if "tied" is in (0, 1)
    out_df["tie_to_next"] = out_df["tied"].isin((0, 1))
    out_df["tie_to_prev"] = out_df["tied"].isin((0, -1))

    if remove_zero_duration_notes:
        # If there are any zero-duration notes (grace notes?), drop them
        out_df = out_df[out_df["onset"] != out_df["release"]]

    out_df["type"] = "note"
    out_df = _add_time_sigs(out_df)
    if measures_df is None:
        LOGGER.warning(
            """Inferring barlines won't give correct results when there is an empty
    measure or when a measure begins with a rest. Use the
    `measures.tsv` files provided in the ABC corpora if possible."""
        )
        out_df = _infer_bars(out_df)
    elif (
        "quarterbeats" not in measures_df.columns
        and "quarterbeats_playthrough" not in measures_df.columns
    ):
        LOGGER.warning(
            """`measures_df` is missing "quarterbeats" column and can't be used."""
        )
        out_df = _infer_bars(out_df)
    else:
        _handle_times(measures_df, fractions)
        out_df = _add_bars_from_measures_df(out_df, measures_df)

    if drop_unused_cols:
        return_columns = [
            "pitch",
            "onset",
            "release",
            "tie_to_next",
            "tie_to_prev",
            "voice",
            "part",
            "spelling",
            "type",
            "other",
        ]

        out_df = out_df[return_columns]
    return sort_df(out_df)

Convert an ms3 dataframe to the format used by this package.

def remap_time_column(x)
Expand source code
remap_time_column = lambda x: Fraction(x).limit_denominator(DENOM_LIMIT)
def tpc2name(tpc: int, minor: bool = False) ‑> str
Expand source code
def tpc2name(tpc: int, minor: bool = False) -> str:
    """Turn a tonal pitch class (TPC) into a name or perform the operation on a
    collection of integers.

    >>> tpc2name(-1)
    'F'
    >>> tpc2name(-1, minor=True)
    'f'
    >>> tpc2name(-8, minor=True)
    'fb'
    >>> tpc2name(6)
    'F#'
    >>> tpc2name(13)
    'F##'

    Based on equivalent function from MS3.

    Args:
      tpc: Tonal pitch class(es) to turn into a note name.
      minor: Pass True if the string is to be returned as lowercase.

    Returns:

    """
    note_names = MINOR_NOTE_NAMES if minor else NOTE_NAMES

    acc, ix = divmod(tpc + 1, 7)
    acc_str = abs(acc) * "b" if acc < 0 else acc * "#"
    return f"{note_names[ix]}{acc_str}"

Turn a tonal pitch class (TPC) into a name or perform the operation on a collection of integers.

>>> tpc2name(-1)
'F'
>>> tpc2name(-1, minor=True)
'f'
>>> tpc2name(-8, minor=True)
'fb'
>>> tpc2name(6)
'F#'
>>> tpc2name(13)
'F##'

Based on equivalent function from MS3.

Args

tpc
Tonal pitch class(es) to turn into a note name.
minor
Pass True if the string is to be returned as lowercase.

Returns: