File: generate_data.py

package info (click to toggle)
mir-eval 0.8.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 8,784 kB
  • sloc: python: 8,364; javascript: 261; makefile: 154
file content (131 lines) | stat: -rwxr-xr-x 4,705 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#!/usr/bin/env python
"""
Generate data for regression tests.
This is a pretty specialized file and should probably only be used if you know
what you're doing.
It expects the following directory structure for data:
    Each task has its own folder in the data directory.
    In each task folder, there are a bunch of file pairs for annotations.
    The reference annotation is ref*.txt, estimated is est*.txt.
    So, e.g., we expect to find data/beat/ref00.txt and data/beat/est00.txt.
    The resulting scores dict from the corresponding task will be written to
    output*.json.
    So, from the example above it would be written to data/beat/output00.json

To use this script, run it as a command-line program:
    ./generate_data.py task1 task2...
task1, task2, etc. are the tasks you'd like to generate data for.
So, for example, if you'd like to generate data for onset and melody,run
    ./generate_data.py onset melody
"""


import mir_eval
import glob
import json
import numpy as np
import os
import sys


def load_separation_data(folder):
    """
    Loads in a stacked matrix of the .wavs in the provided folder.
    We need this because there's no specialized loader in .io for it.
    """
    data = []
    global_fs = None
    # Load in each reference file in the supplied dir
    for reference_file in glob.glob(os.path.join(folder, "*.wav")):
        audio_data, fs = mir_eval.io.load_wav(reference_file)
        # Make sure fs is the same for all files
        assert global_fs is None or fs == global_fs
        global_fs = fs
        data.append(audio_data)
    return np.vstack(data)


def load_transcription_velocity(filename):
    """Loader for data in the format start, end, pitch, velocity."""
    starts, ends, pitches, velocities = mir_eval.io.load_delimited(
        filename, [float, float, int, int]
    )
    # Stack into an interval matrix
    intervals = np.array([starts, ends]).T
    # return pitches and velocities as np.ndarray
    pitches = np.array(pitches)
    velocities = np.array(velocities)

    return intervals, pitches, velocities


if __name__ == "__main__":
    # This dict will contain tuples of (submodule, loader, glob path)
    # The keys are 'beat', 'chord', etc.
    # Whatever is passed in as argv will be grabbed from it and the data for
    # that task will be generated.
    tasks = {}
    tasks["beat"] = (mir_eval.beat, mir_eval.io.load_events, "data/beat/{}*.txt")
    tasks["chord"] = (
        mir_eval.chord,
        mir_eval.io.load_labeled_intervals,
        "data/chord/{}*.lab",
    )
    tasks["melody"] = (
        mir_eval.melody,
        mir_eval.io.load_time_series,
        "data/melody/{}*.txt",
    )
    tasks["multipitch"] = (
        mir_eval.multipitch,
        mir_eval.io.load_ragged_time_series,
        "data/multipitch/()*.txt",
    )
    tasks["onset"] = (mir_eval.onset, mir_eval.io.load_events, "data/onset/{}*.txt")
    tasks["pattern"] = (
        mir_eval.pattern,
        mir_eval.io.load_patterns,
        "data/pattern/{}*.txt",
    )
    tasks["segment"] = (
        mir_eval.segment,
        mir_eval.io.load_labeled_intervals,
        "data/segment/{}*.lab",
    )
    tasks["separation"] = (
        mir_eval.separation,
        load_separation_data,
        "data/separation/{}*",
    )
    tasks["transcription"] = (
        mir_eval.transcription,
        mir_eval.io.load_valued_intervals,
        "data/transcription/{}*.txt",
    )
    tasks["transcription_velocity"] = (
        mir_eval.transcription_velocity,
        load_transcription_velocity,
        "data/transcription_velocity/{}*.txt",
    )
    tasks["key"] = (mir_eval.key, mir_eval.io.load_key, "data/key/{}*.txt")
    # Get task keys from argv
    for task in sys.argv[1:]:
        print(f"Generating data for {task}")
        submodule, loader, data_glob = tasks[task]
        ref_files = sorted(glob.glob(data_glob.format("ref")))
        est_files = sorted(glob.glob(data_glob.format("est")))
        # Cycle through annotation file pairs
        for ref_file, est_file in zip(ref_files, est_files):
            # Use the loader to load in data
            ref_data = loader(ref_file)
            est_data = loader(est_file)
            # Some loaders return tuples, others don't
            if type(ref_data) == tuple:
                scores = submodule.evaluate(*(ref_data + est_data))
            else:
                scores = submodule.evaluate(ref_data, est_data)
            # Write out the resulting scores dict
            output_file = ref_file.replace("ref", "output")
            output_file = os.path.splitext(output_file)[0] + ".json"
            with open(output_file, "w") as f:
                json.dump(scores, f)