code: def _from_timeseries(ts1, ts2, stride, fftlength=None, overlap=None,
                       window=None, **kwargs):
      
      # 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
docs: 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.