def _from_timeseries(ts1, ts2, stride, fftlength=None, overlap=None,
                     window=None, **kwargs):
    """Generate a time-frequency coherence
    :class:`~gwpy.spectrogram.Spectrogram` from a pair of
    :class:`~gwpy.timeseries.TimeSeries`.

    For each `stride`, a PSD :class:`~gwpy.frequencyseries.FrequencySeries`
    is generated, with all resulting spectra stacked in time and returned.
    """
    # check sampling rates
    if ts1.sample_rate.to('Hertz') != ts2.sample_rate.to('Hertz'):
        sampling = min(ts1.sample_rate.value, ts2.sample_rate.value)
        # resample higher rate series
        if ts1.sample_rate.value == sampling:
            ts2 = ts2.resample(sampling)
        else:
            ts1 = ts1.resample(sampling)
    else:
        sampling = ts1.sample_rate.value

    # format FFT parameters
    if fftlength is None:
        fftlength = stride
    if overlap is None:
        overlap = 0

    nstride = int(stride * sampling)

    # get size of spectrogram
    nsteps = int(ts1.size // nstride)
    nfreqs = int(fftlength * sampling // 2 + 1)

    # generate output spectrogram
    out = Spectrogram(zeros((nsteps, nfreqs)), epoch=ts1.epoch, dt=stride,
                      f0=0, df=1/fftlength, copy=True, unit='coherence')

    if not nsteps:
        return out

    # stride through TimeSeries, recording PSDs as columns of spectrogram
    for step in range(nsteps):
        # find step TimeSeries
        idx = nstride * step
        idx_end = idx + nstride
        stepseries1 = ts1[idx:idx_end]
        stepseries2 = ts2[idx:idx_end]
        stepcoh = stepseries1.coherence(stepseries2, fftlength=fftlength,
                                        overlap=overlap, window=window,
                                        **kwargs)
        out.value[step] = stepcoh.value

    return out
Generate a time-frequency coherence
    :class:`~gwpy.spectrogram.Spectrogram` from a pair of
    :class:`~gwpy.timeseries.TimeSeries`.

    For each `stride`, a PSD :class:`~gwpy.frequencyseries.FrequencySeries`
    is generated, with all resulting spectra stacked in time and returned.