
    }Kg0                     ~   d Z ddlZddlZddlmZ ddlmZ ddlm	Z	 dd	gZ
 ej                  d
d
      dej                  dej                  fd       Z ej                  d
d
      d        Z ej                  d
d
      	 ddej                  dej                  dedej                  fd       Z	 ddej                  dej                  dedej                  fdZ	 	 dde	de	dededej                  f
dZ ej                  d
d
      	 	 ddej                  dej                  dej                  dedef
d       Zy)zMatching functions    N   )ParameterError)valid_intervals   )_SequenceLikematch_intervalsmatch_eventsT)nopythoncacheint_aint_bc                     | d   |d   g}|d   |d   k  r|j                          | d   |d   g}|d   |d   k  r|j                          |d   |d   z
  }|dk  rd}|d   |d   z
  }|dkD  r||z  S y)zJaccard similarity between two intervals

    Parameters
    ----------
    int_a, int_b : np.ndarrays, shape=(2,)

    Returns
    -------
    Jaccard similarity between intervals
    r   r   g        )reverse)r   r   endsstartsintersectionunions         Y/home/alanp/www/video.onchill/myenv/lib/python3.12/site-packages/librosa/util/matching.py	__jaccardr      s     !HeAhDAwaAha!Fay6!97VAY&LaGfQiEqye##    c                 N    d}d}|D ]  }t        | ||         }||kD  s||}} |S )z4Find the best Jaccard match from query to candidates)r   )queryintervals_to
candidates
best_scorebest_idxidxscores          r   __match_interval_overlapsr    /   sA     JH%c!23:#(#J	 
 Or   intervals_fromr   strictreturnc                 B   t        j                  |dddf         }t        j                  |dddf         }||df   }||df   }t        j                  || dddf   d      }t        j                  || dddf   d      }t        j                  t	        |       t
        j                        }	t        t	        |             D ]  }
| |
   }||
   }||
   }t        |d|       t        ||d       z  }t	        |      dkD  rt        |||      |	|
<   N|rt        t         j                  }t         j                  }||
   dkD  r|d   |||
   dz
     z
  }||
   dz   t	        |      k  r|||
   dz      |d   z
  }||k  r|||
   dz
     |	|
<   |||
   dz      |	|
<    |	S )z.Numba-accelerated interval matching algorithm.Nr   r   right)sideleftdtype)npargsortsearchsortedemptylennumbauint32rangesetr    r   inf)r!   r   r"   start_index	end_indexstart_sorted
end_sortedsearch_endssearch_startsoutputir   after_querybefore_queryr   dist_before
dist_afters                    r   __match_intervalsr@   <   s    **\!Q$/0K 

<1-.I  Q/Lil+J//,q!t0D7SKOOJq!t0D6RMXXc.)>F3~&'q! "!n$Q' \k23c)LM:R6SS
 z?Q1%zRF1I  
 &&KJQ!##AhM!4Dq4H)II1~!C$55)+a.1*<=aH
Z'%mA&6&:;q	'A(:;q	= (> Mr   c                     t        |       dk(  st        |      dk(  rt        d      t        |        t        |       	 t        | ||      S # t        $ r}t        d|       |d}~ww xY w)a
  Match one set of time intervals to another.

    This can be useful for tasks such as mapping beat timings
    to segments.

    Each element ``[a, b]`` of ``intervals_from`` is matched to the
    element ``[c, d]`` of ``intervals_to`` which maximizes the
    Jaccard similarity between the intervals::

        max(0, |min(b, d) - max(a, c)|) / |max(d, b) - min(a, c)|

    In ``strict=True`` mode, if there is no interval with positive
    intersection with ``[a,b]``, an exception is thrown.

    In ``strict=False`` mode, any interval ``[a, b]`` that has no
    intersection with any element of ``intervals_to`` is instead
    matched to the interval ``[c, d]`` which minimizes::

        min(|b - c|, |a - d|)

    that is, the disjoint interval [c, d] with a boundary closest
    to [a, b].

    .. note:: An element of ``intervals_to`` may be matched to multiple
       entries of ``intervals_from``.

    Parameters
    ----------
    intervals_from : np.ndarray [shape=(n, 2)]
        The time range for source intervals.
        The ``i`` th interval spans time ``intervals_from[i, 0]``
        to ``intervals_from[i, 1]``.
        ``intervals_from[0, 0]`` should be 0, ``intervals_from[-1, 1]``
        should be the track duration.
    intervals_to : np.ndarray [shape=(m, 2)]
        Analogous to ``intervals_from``.
    strict : bool
        If ``True``, intervals can only match if they intersect.
        If ``False``, disjoint intervals can match.

    Returns
    -------
    interval_mapping : np.ndarray [shape=(n,)]
        For each interval in ``intervals_from``, the
        corresponding interval in ``intervals_to``.

    See Also
    --------
    match_events

    Raises
    ------
    ParameterError
        If either array of input intervals is not the correct shape

        If ``strict=True`` and some element of ``intervals_from`` is disjoint from
        every element of ``intervals_to``.

    Examples
    --------
    >>> ints_from = np.array([[3, 5], [1, 4], [4, 5]])
    >>> ints_to = np.array([[0, 2], [1, 3], [4, 5], [6, 7]])
    >>> librosa.util.match_intervals(ints_from, ints_to)
    array([2, 1, 2], dtype=uint32)
    >>> # [3, 5] => [4, 5]  (ints_to[2])
    >>> # [1, 4] => [1, 3]  (ints_to[1])
    >>> # [4, 5] => [4, 5]  (ints_to[2])

    The reverse matching of the above is not possible in ``strict`` mode
    because ``[6, 7]`` is disjoint from all intervals in ``ints_from``.
    With ``strict=False``, we get the following:

    >>> librosa.util.match_intervals(ints_to, ints_from, strict=False)
    array([1, 1, 2, 2], dtype=uint32)
    >>> # [0, 2] => [1, 4]  (ints_from[1])
    >>> # [1, 3] => [1, 4]  (ints_from[1])
    >>> # [4, 5] => [4, 5]  (ints_from[2])
    >>> # [6, 7] => [4, 5]  (ints_from[2])
    r   z'Attempting to match empty interval list)r"   z&Unable to match intervals with strict=N)r.   r   r   r@   )r!   r   r"   excs       r   r   r   r   sy    d >a3|#4#9FGG N#L!Y fMM YEfXNOUXXYs   A 	A*A%%A*events_from	events_tor'   r%   c                    t        |       dk(  st        |      dk(  rt        d      |s6|s4t        j                  t        j                  | |            st        d      |s"t        |      t        |       k  rt        d      |s"t        |      t        |       kD  rt        d      t        j                  | t        j                        }t        || |||      S )a  Match one set of events to another.

    This is useful for tasks such as matching beats to the nearest
    detected onsets, or frame-aligned events to the nearest zero-crossing.

    .. note:: A target event may be matched to multiple source events.

    Examples
    --------
    >>> # Sources are multiples of 7
    >>> s_from = np.arange(0, 100, 7)
    >>> s_from
    array([ 0,  7, 14, 21, 28, 35, 42, 49, 56, 63, 70, 77, 84, 91,
           98])
    >>> # Targets are multiples of 10
    >>> s_to = np.arange(0, 100, 10)
    >>> s_to
    array([ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90])
    >>> # Find the matching
    >>> idx = librosa.util.match_events(s_from, s_to)
    >>> idx
    array([0, 1, 1, 2, 3, 3, 4, 5, 6, 6, 7, 8, 8, 9, 9])
    >>> # Print each source value to its matching target
    >>> zip(s_from, s_to[idx])
    [(0, 0), (7, 10), (14, 10), (21, 20), (28, 30), (35, 30),
     (42, 40), (49, 50), (56, 60), (63, 60), (70, 70), (77, 80),
     (84, 80), (91, 90), (98, 90)]

    Parameters
    ----------
    events_from : ndarray [shape=(n,)]
        Array of events (eg, times, sample or frame indices) to match from.
    events_to : ndarray [shape=(m,)]
        Array of events (eg, times, sample or frame indices) to
        match against.
    left : bool
    right : bool
        If ``False``, then matched events cannot be to the left (or right)
        of source events.

    Returns
    -------
    event_mapping : np.ndarray [shape=(n,)]
        For each event in ``events_from``, the corresponding event
        index in ``events_to``::

            event_mapping[i] == arg min |events_from[i] - events_to[:]|

    See Also
    --------
    match_intervals

    Raises
    ------
    ParameterError
        If either array of input events is not the correct shape
    r   z$Attempting to match empty event listzWCannot match events with left=right=False and events_from is not contained in events_tozICannot match events with left=False and max(events_to) < max(events_from)zJCannot match events with right=False and min(events_to) > min(events_from)r(   )
r.   r   r*   allin1dmaxmin
empty_likeint32__match_events_helper)rC   rD   r'   r%   r:   s        r   r	   r	      s    ~ ;1I! 3CDD E266"''+y*I#J
 	
 c)ns;'774
 	
 s9~K(884
 	
 ]];bhh7F !iuMMr   r:   c                    t        j                  |      }||   }t        j                  |      }||   }t        j                  ||      }	t        |	      D ]  \  }
}d}d}d}t	        |	      }d}d}d}|	|
   }||
   }|t	        |      k(  r|dz  }|r|dkD  r|dz
  }d}|r|t	        |      dz
  k  r|dz   }d}t        ||   |z
        }|r|rt        ||   |z
        }|r|rt        ||   |z
        }|r$|s||   |kD  s|s||k  s
||k  r||k  r	||   | |
<   |r||k  r	||   | |
<   ||   | |
<    t        j                  |       }| ||<   |S )NFr   r   r   T)r*   r+   r,   	enumerater.   absrJ   )r:   rC   rD   r'   r%   from_idxsorted_fromto_idx	sorted_tomatching_indicesind
middle_ind	left_flag
right_flagleft_ind	right_ind	left_diff
right_diffmid_diffsorted_from_num	solutionss                        r   rL   rL   4  s    zz+&Hh'KZZ	"F&!I y+> %%56Z	
()		
%c*
%c* Y'!OJ JN!A~HI Z#i.1"44"QIJy,>?IIh//ABIZYy1OCDJ:&89x#7J&9x+? *F3K Z(2 +F3K !,F3Ka 7f f%I Ihr   )T)TT)__doc__numpyr*   r/   
exceptionsr   utilsr   _typingr   __all__jitndarrayr   r    boolr@   r   r	   rL    r   r   <module>rj      s      & " #n
- D%RZZ 

  &> D%	 &	 D%IM2JJ2.0jj2BF2ZZ2 &2l JN]YJJ]Y.0jj]YBF]YZZ]YF 	_N_N_N _N 	_N
 ZZ_ND D%
 HJJHH zzH 	H
 H &Hr   