Skip to content

Commit

Permalink
deprecating separation module (#382)
Browse files Browse the repository at this point in the history
* deprecating separation module

* skip separation tests

* blacking

* omit separation.py from coverage

* fix test failures due to legend locations in matplotlib 3.9

* skip separation tests in display

* blacked tests
  • Loading branch information
bmcfee authored Aug 16, 2024
1 parent fddf120 commit 1fed532
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 13 deletions.
2 changes: 0 additions & 2 deletions .coveragerc

This file was deleted.

11 changes: 11 additions & 0 deletions mir_eval/separation.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# -*- coding: utf-8 -*-
"""
.. warning::
The mir_eval.separation module is deprecated in mir_eval version 0.8, and will be removed.
We recommend that you migrate your code to use an alternative package such as sigsep-museval
https://sigsep.github.io/sigsep-mus-eval/
Source separation algorithms attempt to extract recordings of individual
sources from a recording of a mixture of sources. Evaluation methods for
source separation compare the extracted sources from reference sources and
Expand Down Expand Up @@ -141,6 +147,7 @@ def _any_source_silent(sources):
)


@util.deprecated(version="0.8", version_removed="0.9")
def bss_eval_sources(reference_sources, estimated_sources, compute_permutation=True):
"""
Ordering and measurement of the separation quality for estimated source
Expand Down Expand Up @@ -251,6 +258,7 @@ def bss_eval_sources(reference_sources, estimated_sources, compute_permutation=T
return (sdr, sir, sar, popt)


@util.deprecated(version="0.8", version_removed="0.9")
def bss_eval_sources_framewise(
reference_sources,
estimated_sources,
Expand Down Expand Up @@ -362,6 +370,7 @@ def bss_eval_sources_framewise(
return sdr, sir, sar, perm


@util.deprecated(version="0.8", version_removed="0.9")
def bss_eval_images(reference_sources, estimated_sources, compute_permutation=True):
"""Compute the bss_eval_images function from the
BSS_EVAL Matlab toolbox.
Expand Down Expand Up @@ -496,6 +505,7 @@ def bss_eval_images(reference_sources, estimated_sources, compute_permutation=Tr
return (sdr, isr, sir, sar, popt)


@util.deprecated(version="0.8", version_removed="0.9")
def bss_eval_images_framewise(
reference_sources,
estimated_sources,
Expand Down Expand Up @@ -841,6 +851,7 @@ def _safe_db(num, den):
return 10 * np.log10(num / den)


@util.deprecated(version="0.8", version_removed="0.9")
def evaluate(reference_sources, estimated_sources, **kwargs):
"""Compute all metrics for the given reference and estimated signals.
Expand Down
21 changes: 21 additions & 0 deletions mir_eval/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

import os
import inspect
import warnings
from decorator import decorator

import numpy as np

Expand Down Expand Up @@ -939,3 +941,22 @@ def midi_to_hz(midi):
Frequency/frequencies in Hz corresponding to `midi`
"""
return 440.0 * (2.0 ** ((midi - 69.0) / 12.0))


def deprecated(*, version, version_removed):
"""Mark a function as deprecated.
Using the decorated (old) function will result in a warning.
"""

def __wrapper(func, *args, **kwargs):
"""Warn the user, and then proceed."""
warnings.warn(
f"{func.__module__}.{func.__name__}\n\tDeprecated as of mir_eval version {version}."
f"\n\tIt will be removed in mir_eval version {version_removed}.",
category=FutureWarning,
stacklevel=3, # Would be 2, but the decorator adds a level
)
return func(*args, **kwargs)

return decorator(__wrapper)
9 changes: 8 additions & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
[tool:pytest]
addopts = --cov-report term-missing --cov mir_eval --cov-report=xml --mpl --mpl-baseline-path=baseline_images/test_display

[coverage:report]
show_missing = True

[coverage:run]
omit =
separation.py

[pydocstyle]
# convention = numpy
# Below is equivalent to numpy convention + D400 and D205
Expand Down Expand Up @@ -48,13 +55,13 @@ keywords = audio music mir dsp
install_requires =
numpy >= 1.15.4
scipy >= 1.4.0
decorator

[options.extras_require]
display =
matplotlib >= 3.3.0
tests =
matplotlib >= 3.3.0
decorator
pytest
pytest-cov
pytest-mpl
18 changes: 10 additions & 8 deletions tests/test_display.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def test_display_segment():
mir_eval.display.segments(intervals, labels, text=False)

# Draw a legend
plt.legend()
plt.legend(loc="upper right")
return plt.gcf()


Expand Down Expand Up @@ -126,7 +126,7 @@ def test_display_labeled_intervals_compare():
)
mir_eval.display.labeled_intervals(est_int, est_labels, alpha=0.5, label="Estimate")

plt.legend()
plt.legend(loc="upper right")
return plt.gcf()


Expand Down Expand Up @@ -198,7 +198,7 @@ def test_display_hierarchy_nolabel():
# Plot reference and estimate with a common label set
mir_eval.display.hierarchy([int0, int1], [lab0, lab1])

plt.legend()
plt.legend(loc="upper right")
return plt.gcf()


Expand All @@ -218,7 +218,7 @@ def test_display_hierarchy_label():
# Plot reference and estimate with a common label set
mir_eval.display.hierarchy([int0, int1], [lab0, lab1], levels=["Large", "Small"])

plt.legend()
plt.legend(loc="upper right")
return plt.gcf()


Expand All @@ -238,7 +238,7 @@ def test_display_pitch_hz():
# Plot pitches on a Hz scale
mir_eval.display.pitch(ref_times, ref_freqs, unvoiced=True, label="Reference")
mir_eval.display.pitch(est_times, est_freqs, unvoiced=True, label="Estimate")
plt.legend()
plt.legend(loc="upper left")
return plt.gcf()


Expand Down Expand Up @@ -323,7 +323,7 @@ def test_display_multipitch_midi():
mir_eval.display.multipitch(ref_t, ref_p, midi=True, alpha=0.5, label="Reference")
mir_eval.display.multipitch(est_t, est_p, midi=True, alpha=0.5, label="Estimate")

plt.legend()
plt.legend(loc="upper left")
return plt.gcf()


Expand Down Expand Up @@ -392,6 +392,7 @@ def test_display_ticker_midi_zoom():
tolerance=6,
)
@pytest.mark.xfail(OLD_FT, reason=f"freetype version < {FT_VERSION}", strict=False)
@pytest.mark.skip()
def test_display_separation():
plt.figure()

Expand All @@ -410,6 +411,7 @@ def test_display_separation():
tolerance=6,
)
@pytest.mark.xfail(OLD_FT, reason=f"freetype version < {FT_VERSION}", strict=False)
@pytest.mark.skip()
def test_display_separation_label():
plt.figure()

Expand All @@ -419,7 +421,7 @@ def test_display_separation_label():

mir_eval.display.separation([x0, x1, x2], fs=fs, labels=["Alice", "Bob", "Carol"])

plt.legend()
plt.legend(loc="upper right")
return plt.gcf()


Expand All @@ -439,7 +441,7 @@ def test_display_events():
# Plot both with labels
mir_eval.display.events(beats_ref, label="reference")
mir_eval.display.events(beats_est, label="estimate")
plt.legend()
plt.legend(loc="upper right")
return plt.gcf()


Expand Down
8 changes: 6 additions & 2 deletions tests/test_separation.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
assert len(ref_files) == len(est_files) == len(sco_files) > 0
file_sets = list(zip(ref_files, est_files, sco_files))

# Skip separation tests since deprecation
pytest.skip(allow_module_level=True)


@pytest.fixture
def separation_data(request):
Expand Down Expand Up @@ -119,8 +122,9 @@ def test_empty_input(metric):
# And that the metric returns empty arrays
assert np.allclose(metric(*args), np.array([]))

assert "reference_sources is empty" in str(record[0].message)
assert "estimated_sources is empty" in str(record[1].message)
# These warning counters are now offset by 1 because of the deprecation message
assert "reference_sources is empty" in str(record[1].message)
assert "estimated_sources is empty" in str(record[2].message)


@pytest.mark.parametrize(
Expand Down

0 comments on commit 1fed532

Please sign in to comment.