<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def match_notes( ref_intervals, ref_pitches, ref_velocities, est_intervals, est_pitches, est_velocities, onset_tolerance=0.05, pitch_tolerance=50.0, offset_ratio=0.2, offset_min_tolerance=0.05, strict=False, velocity_tolerance=0.1):
 """Match notes, taking note velocity into consideration. This function first calls :func:`mir_eval.transcription.match_notes` to match notes according to the supplied intervals, pitches, onset, offset, and pitch tolerances. The velocities of the matched notes are then used to estimate a slope and intercept which can rescale the estimated velocities so that they are as close as possible (in L2 sense) to their matched reference velocities. Velocities are then normalized to the range [0, 1]. A estimated note is then further only considered correct if its velocity is within ``velocity_tolerance`` of its matched (according to pitch and timing) reference note. Parameters ref_intervals : np.ndarray, shape=(n,2) Array of reference notes time intervals (onset and offset times) ref_pitches : np.ndarray, shape=(n,) Array of reference pitch values in Hertz ref_velocities : np.ndarray, shape=(n,) Array of MIDI velocities (i.e. between 0 and 127) of reference notes est_intervals : np.ndarray, shape=(m,2) Array of estimated notes time intervals (onset and offset times) est_pitches : np.ndarray, shape=(m,) Array of estimated pitch values in Hertz est_velocities : np.ndarray, shape=(m,) Array of MIDI velocities (i.e. between 0 and 127) of estimated notes onset_tolerance : float > 0 The tolerance for an estimated note's onset deviating from the reference note's onset, in seconds. Default is 0.05 (50 ms). pitch_tolerance : float > 0 The tolerance for an estimated note's pitch deviating from the reference note's pitch, in cents. Default is 50.0 (50 cents). offset_ratio : float > 0 or None The ratio of the reference note's duration used to define the offset_tolerance. Default is 0.2 (20%), meaning the ``offset_tolerance`` will equal the ``ref_duration * 0.2``, or 0.05 (50 ms), whichever is greater. If ``offset_ratio`` is set to ``None``, offsets are ignored in the matching. offset_min_tolerance : float > 0 The minimum tolerance for offset matching. See offset_ratio description for an explanation of how the offset tolerance is determined. Note: this parameter only influences the results if ``offset_ratio`` is not ``None``. strict : bool If ``strict=False`` (the default), threshold checks for onset, offset, and pitch matching are performed using ``<=`` (less than or equal). If ``strict=True``, the threshold checks are performed using ``<`` (less than). velocity_tolerance : float > 0 Estimated notes are considered correct if, after rescaling and normalization to [0, 1], they are within ``velocity_tolerance`` of a matched reference note. Returns ------- matching : list of tuples A list of matched reference and estimated notes. ``matching[i] == (i, j)`` where reference note ``i`` matches estimated note ``j``. """

    # Compute note matching as usual using standard transcription function
    matching = transcription.match_notes(
        ref_intervals, ref_pitches, est_intervals, est_pitches,
        onset_tolerance, pitch_tolerance, offset_ratio, offset_min_tolerance,
        strict)

    # Rescale reference velocities to the range [0, 1]
    min_velocity, max_velocity = np.min(ref_velocities), np.max(ref_velocities)
    # Make the smallest possible range 1 to avoid divide by zero
    velocity_range = max(1, max_velocity - min_velocity)
    ref_velocities = (ref_velocities - min_velocity)/float(velocity_range)

    # Convert matching list-of-tuples to array for fancy indexing
    matching = np.array(matching)
    # When there is no matching, return an empty list
    if matching.size == 0:
        return []
    # Grab velocities for matched notes
    ref_matched_velocities = ref_velocities[matching[:, 0]]
    est_matched_velocities = est_velocities[matching[:, 1]]
    # Find slope and intercept of line which produces best least-squares fit
    # between matched est and ref velocities
    slope, intercept = np.linalg.lstsq(
        np.vstack([est_matched_velocities,
                   np.ones(len(est_matched_velocities))]).T,
        ref_matched_velocities)[0]
    # Re-scale est velocities to match ref
    est_matched_velocities = slope*est_matched_velocities + intercept
    # Compute the absolute error of (rescaled) estimated velocities vs.
    # normalized reference velocities. Error will be in [0, 1]
    velocity_diff = np.abs(est_matched_velocities - ref_matched_velocities)
    # Check whether each error is within the provided tolerance
    velocity_within_tolerance = (velocity_diff < velocity_tolerance)
    # Only keep matches whose velocity was within the provided tolerance
    matching = matching[velocity_within_tolerance]
    # Convert back to list-of-tuple format
    matching = [tuple(_) for _ in matching]

    return matching