#NEWLINE# @ cache #NEWLINE# def sync( data , idx , aggregate = None , pad = True , axis = ( - 1 ) ) : #NEWLINE# #INDENT# "Synchronous aggregation of a multi-dimensional array between boundaries\n\n    .. note::\n        In order to ensure total coverage, boundary points may be added\n        to `idx`.\n\n        If synchronizing a feature matrix against beat tracker output, ensure\n        that frame index numbers are properly aligned and use the same hop length.\n\n    Parameters\n    ----------\n    data      : np.ndarray\n        multi-dimensional array of features\n\n    idx : iterable of ints or slices\n        Either an ordered array of boundary indices, or\n        an iterable collection of slice objects.\n\n\n    aggregate : function\n        aggregation function (default: `np.mean`)\n\n    pad : boolean\n        If `True`, `idx` is padded to span the full range `[0, data.shape[axis]]`\n\n    axis : int\n        The axis along which to aggregate data\n\n    Returns\n    -------\n    data_sync : ndarray\n        `data_sync` will have the same dimension as `data`, except that the `axis`\n        coordinate will be reduced according to `idx`.\n\n        For example, a 2-dimensional `data` with `axis=-1` should satisfy\n\n        `data_sync[:, i] = aggregate(data[:, idx[i-1]:idx[i]], axis=-1)`\n\n    Raises\n    ------\n    ParameterError\n        If the index set is not of consistent type (all slices or all integers)\n\n    Examples\n    --------\n    Beat-synchronous CQT spectra\n\n    >>> y, sr = librosa.load(librosa.util.example_audio_file())\n    >>> tempo, beats = librosa.beat.beat_track(y=y, sr=sr)\n    >>> cqt = librosa.cqt(y=y, sr=sr)\n\n    By default, use mean aggregation\n\n    >>> cqt_avg = librosa.util.sync(cqt, beats)\n\n    Use median-aggregation instead of mean\n\n    >>> cqt_med = librosa.util.sync(cqt, beats,\n    ...                                aggregate=np.median)\n\n    Or sub-beat synchronization\n\n    >>> sub_beats = librosa.segment.subsegment(cqt, beats)\n    >>> cqt_med_sub = librosa.util.sync(cqt, sub_beats, aggregate=np.median)\n\n\n    Plot the results\n\n    >>> import matplotlib.pyplot as plt\n    >>> plt.figure()\n    >>> plt.subplot(3, 1, 1)\n    >>> librosa.display.specshow(librosa.logamplitude(cqt**2,\n    ...                                               ref_power=np.max),\n    ...                          x_axis='time')\n    >>> plt.colorbar(format='%+2.0f dB')\n    >>> plt.title('CQT power, shape={}'.format(cqt.shape))\n    >>> plt.subplot(3, 1, 2)\n    >>> librosa.display.specshow(librosa.logamplitude(cqt_med**2,\n    ...                                               ref_power=np.max))\n    >>> plt.colorbar(format='%+2.0f dB')\n    >>> plt.title('Beat synchronous CQT power, '\n    ...           'shape={}'.format(cqt_med.shape))\n    >>> plt.subplot(3, 1, 3)\n    >>> librosa.display.specshow(librosa.logamplitude(cqt_med_sub**2,\n    ...                                               ref_power=np.max))\n    >>> plt.colorbar(format='%+2.0f dB')\n    >>> plt.title('Sub-beat synchronous CQT power, '\n    ...           'shape={}'.format(cqt_med_sub.shape))\n    >>> plt.tight_layout()\n\n    " #NEWLINE# if ( aggregate is None ) : #NEWLINE# #INDENT# aggregate = np . mean #NEWLINE# #UNINDENT# shape = list ( data . shape ) #NEWLINE# if np . all ( [ isinstance ( _ , slice ) for _ in idx ] ) : #NEWLINE# #INDENT# slices = idx #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# if np . all ( [ np . issubdtype ( type ( _ ) , np . int ) for _ in idx ] ) : #NEWLINE# #INDENT# slices = index_to_slice ( np . asarray ( idx ) , 0 , shape [ axis ] , pad = pad ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# raise ParameterError ( 'Invalid index set: {}' . format ( idx ) ) #NEWLINE# #UNINDENT# #UNINDENT# agg_shape = list ( shape ) #NEWLINE# agg_shape [ axis ] = len ( slices ) #NEWLINE# data_agg = np . empty ( agg_shape , order = ( 'F' if np . isfortran ( data ) else 'C' ) , dtype = data . dtype ) #NEWLINE# idx_in = ( [ slice ( None ) ] * data . ndim ) #NEWLINE# idx_agg = ( [ slice ( None ) ] * data_agg . ndim ) #NEWLINE# for ( i , segment ) in enumerate ( slices ) : #NEWLINE# #INDENT# idx_in [ axis ] = segment #NEWLINE# idx_agg [ axis ] = i #NEWLINE# data_agg [ idx_agg ] = aggregate ( data [ idx_in ] , axis = axis ) #NEWLINE# #UNINDENT# return data_agg