def compute(i, j):
     if i == j:
         return 1.0
     else:
         if tau is None:
             tau_mat = spq.minimum(
                 *spq.meshgrid(auto_taus[i], auto_taus[j])) / 2.0
         else:
             tau_mat = sp.tile(tau, (trains[j].size, trains[i].size))
         coincidence = sp.sum(
             kernel((trains[i] - sp.atleast_2d(trains[j]).T) / tau_mat))
         normalization = 1.0 / sp.sqrt(trains[i].size * trains[j].size)
         return normalization * coincidence
 def compute(i, j):
     if i == j:
         return 1.0
     else:
         if tau is None:
             tau_mat = spq.minimum(*spq.meshgrid(
                 auto_taus[i], auto_taus[j])) / 2.0
         else:
             tau_mat = sp.tile(tau, (trains[j].size, trains[i].size))
         coincidence = sp.sum(kernel(
             (trains[i] - sp.atleast_2d(trains[j]).T) / tau_mat))
         normalization = 1.0 / sp.sqrt(trains[i].size * trains[j].size)
         return normalization * coincidence
def event_synchronization(
        trains, tau=None,
        kernel=sigproc.RectangularKernel(1.0, normalize=False), sort=True):
    """ event_synchronization(trains, tau=None, kernel=signal_processing.RectangularKernel(1.0, normalize=False), sort=True)

    Calculates the event synchronization.

    Let :math:`d(x|y)` be the count of spikes in :math:`y` which occur shortly
    before an event in :math:`x` with a time difference of less than
    :math:`\\tau`. Moreover, let :math:`n_x` and :math:`n_y` be the number of
    total spikes in the spike trains :math:`x` and :math:`y`. The event
    synchrony is then defined as :math:`Q_T = \\frac{d(x|y)
    + d(y|x)}{\\sqrt{n_x n_y}}`.

    The time maximum time lag :math:`\\tau` can be determined automatically for
    each pair of spikes :math:`t^x_i` and :math:`t^y_j` by the formula
    :math:`\\tau_{ij} = \\frac{1}{2} \\min\{t^x_{i+1} - t^x_i, t^x_i - t^x_{i-1},
    t^y_{j+1} - t^y_j, t^y_j - t^y_{j-1}\}`

    Further and more detailed information can be found in
    *Quiroga, R. Q., Kreuz, T., & Grassberger, P. (2002). Event
    synchronization: a simple and fast method to measure synchronicity and time
    delay patterns. Physical Review E, 66(4), 041904.*

    :param sequence trains: Sequence of :class:`neo.core.SpikeTrain` objects of
        which the van Rossum distance will be calculated pairwise.
    :param tau: The maximum time lag for two spikes to be considered coincident
        or synchronous as time scalar. To have it determined automatically by
        above formula set it to `None`.
    :type tau: Quantity scalar
    :param kernel: Kernel to use in the calculation of the distance.
    :type kernel: :class:`.signal_processing.Kernel`
    :param bool sort: Spike trains with sorted spike times are be needed for
        the calculation. You can set `sort` to `False` if you know that your
        spike trains are already sorted to decrease calculation time.
    :returns: Matrix containing the event synchronization for all pairs of spike
        trains.
    :rtype: 2-D array
    """

    trains = [st.view(type=pq.Quantity) for st in trains]
    if sort:
        trains = [sp.sort(st) for st in trains]

    if tau is None:
        inf_array = sp.array([sp.inf])
        isis = [spq.concatenate(
                (inf_array * st.units, sp.diff(st), inf_array * st.units))
                for st in trains]
        auto_taus = [spq.minimum(t[:-1], t[1:]) for t in isis]

    def compute(i, j):
        if i == j:
            return 1.0
        else:
            if tau is None:
                tau_mat = spq.minimum(*spq.meshgrid(
                    auto_taus[i], auto_taus[j])) / 2.0
            else:
                tau_mat = sp.tile(tau, (trains[j].size, trains[i].size))
            coincidence = sp.sum(kernel(
                (trains[i] - sp.atleast_2d(trains[j]).T) / tau_mat))
            normalization = 1.0 / sp.sqrt(trains[i].size * trains[j].size)
            return normalization * coincidence

    return _create_matrix_from_indexed_function(
        (len(trains), len(trains)), compute, kernel.is_symmetric())
def event_synchronization(trains,
                          tau=None,
                          kernel=sigproc.RectangularKernel(1.0,
                                                           normalize=False),
                          sort=True):
    """ event_synchronization(trains, tau=None, kernel=signal_processing.RectangularKernel(1.0, normalize=False), sort=True)

    Calculates the event synchronization.

    Let :math:`d(x|y)` be the count of spikes in :math:`y` which occur shortly
    before an event in :math:`x` with a time difference of less than
    :math:`\\tau`. Moreover, let :math:`n_x` and :math:`n_y` be the number of
    total spikes in the spike trains :math:`x` and :math:`y`. The event
    synchrony is then defined as :math:`Q_T = \\frac{d(x|y)
    + d(y|x)}{\\sqrt{n_x n_y}}`.

    The time maximum time lag :math:`\\tau` can be determined automatically for
    each pair of spikes :math:`t^x_i` and :math:`t^y_j` by the formula
    :math:`\\tau_{ij} = \\frac{1}{2} \\min\{t^x_{i+1} - t^x_i, t^x_i - t^x_{i-1},
    t^y_{j+1} - t^y_j, t^y_j - t^y_{j-1}\}`

    Further and more detailed information can be found in
    *Quiroga, R. Q., Kreuz, T., & Grassberger, P. (2002). Event
    synchronization: a simple and fast method to measure synchronicity and time
    delay patterns. Physical Review E, 66(4), 041904.*

    :param sequence trains: Sequence of :class:`neo.core.SpikeTrain` objects of
        which the van Rossum distance will be calculated pairwise.
    :param tau: The maximum time lag for two spikes to be considered coincident
        or synchronous as time scalar. To have it determined automatically by
        above formula set it to `None`.
    :type tau: Quantity scalar
    :param kernel: Kernel to use in the calculation of the distance.
    :type kernel: :class:`.signal_processing.Kernel`
    :param bool sort: Spike trains with sorted spike times are be needed for
        the calculation. You can set `sort` to `False` if you know that your
        spike trains are already sorted to decrease calculation time.
    :returns: Matrix containing the event synchronization for all pairs of spike
        trains.
    :rtype: 2-D array
    """

    trains = [st.view(type=pq.Quantity) for st in trains]
    if sort:
        trains = [sp.sort(st) for st in trains]

    if tau is None:
        inf_array = sp.array([sp.inf])
        isis = [
            spq.concatenate(
                (inf_array * st.units, sp.diff(st), inf_array * st.units))
            for st in trains
        ]
        auto_taus = [spq.minimum(t[:-1], t[1:]) for t in isis]

    def compute(i, j):
        if i == j:
            return 1.0
        else:
            if tau is None:
                tau_mat = spq.minimum(
                    *spq.meshgrid(auto_taus[i], auto_taus[j])) / 2.0
            else:
                tau_mat = sp.tile(tau, (trains[j].size, trains[i].size))
            coincidence = sp.sum(
                kernel((trains[i] - sp.atleast_2d(trains[j]).T) / tau_mat))
            normalization = 1.0 / sp.sqrt(trains[i].size * trains[j].size)
            return normalization * coincidence

    return _create_matrix_from_indexed_function((len(trains), len(trains)),
                                                compute, kernel.is_symmetric())