# -*- coding: utf-8 -*-
'''
Functions to calculate spike-triggered average and spike-field coherence of
analog signals.

:copyright: Copyright 2015-2016 by the Elephant team, see `doc/authors.rst`.
:license: Modified BSD, see LICENSE.txt for details.
'''

from __future__ import division, print_function, unicode_literals

import numpy as np
import scipy.signal
import quantities as pq
from neo.core import AnalogSignal, SpikeTrain
import warnings
from .conversion import BinnedSpikeTrain


def spike_triggered_average(signal, spiketrains, window):
    """
    Calculates the spike-triggered averages of analog signals in a time window
    relative to the spike times of a corresponding spiketrain for multiple
    signals each. The function receives n analog signals and either one or
    n spiketrains. In case it is one spiketrain this one is muliplied n-fold
    and used for each of the n analog signals.

    Parameters
    ----------
    signal : neo AnalogSignal object
        'signal' contains n analog signals.
    spiketrains : one SpikeTrain or one numpy ndarray or a list of n of either of these.
        'spiketrains' contains the times of the spikes in the spiketrains.
    window : tuple of 2 Quantity objects with dimensions of time.
        'window' is the start time and the stop time, relative to a spike, of
        the time interval for signal averaging.
        If the window size is not a multiple of the sampling interval of the
        signal the window will be extended to the next multiple.

    Returns
    -------
    result_sta : neo AnalogSignal object
        'result_sta' contains the spike-triggered averages of each of the
        analog signals with respect to the spikes in the corresponding
        spiketrains. The length of 'result_sta' is calculated as the number
        of bins from the given start and stop time of the averaging interval
        and the sampling rate of the analog signal. If for an analog signal
        no spike was either given or all given spikes had to be ignored
        because of a too large averaging interval, the corresponding returned
        analog signal has all entries as nan. The number of used spikes and
        unused spikes for each analog signal are returned as annotations to
        the returned AnalogSignal object.

    Examples
    --------

    >>> signal = neo.AnalogSignal(np.array([signal1, signal2]).T, units='mV',
    ...                                sampling_rate=10/ms)
    >>> stavg = spike_triggered_average(signal, [spiketrain1, spiketrain2],
    ...                                 (-5 * ms, 10 * ms))

    """

    # checking compatibility of data and data types
    # window_starttime: time to specify the start time of the averaging
    # interval relative to a spike
    # window_stoptime: time to specify the stop time of the averaging
    # interval relative to a spike
    window_starttime, window_stoptime = window
    if not (isinstance(window_starttime, pq.quantity.Quantity) and
            window_starttime.dimensionality.simplified ==
            pq.Quantity(1, "s").dimensionality):
        raise TypeError("The start time of the window (window[0]) "