Instruction:
Can you create a Python 3 function that
saves all open matplotlib figures of the example code - block.

Response:
def save_figures(image_path, fig_count, gallery_conf):
    """Save all open matplotlib figures of the example code-block

    Parameters
    ----------
    image_path : str
        Path where plots are saved (format string which accepts figure number)
    fig_count : int
        Previous figure number count. Figure number add from this number

    Returns
    -------
    list of strings containing the full path to each figure
    """
    figure_list = []

    fig_managers = matplotlib._pylab_helpers.Gcf.get_all_fig_managers()
    for fig_mngr in fig_managers:
        # Set the fig_num figure as the current figure as we can't
        # save a figure that's not the current figure.
        fig = plt.figure(fig_mngr.num)
        kwargs = {}
        to_rgba = matplotlib.colors.colorConverter.to_rgba
        for attr in ['facecolor', 'edgecolor']:
            fig_attr = getattr(fig, 'get_' + attr)()
            default_attr = matplotlib.rcParams['figure.' + attr]
            if to_rgba(fig_attr) != to_rgba(default_attr):
                kwargs[attr] = fig_attr

        current_fig = image_path.format(fig_count + fig_mngr.num)
        fig.savefig(current_fig, **kwargs)
        figure_list.append(current_fig)

    if gallery_conf.get('find_mayavi_figures', False):
        from mayavi import mlab
        e = mlab.get_engine()
        last_matplotlib_fig_num = len(figure_list)
        total_fig_num = last_matplotlib_fig_num + len(e.scenes)
        mayavi_fig_nums = range(last_matplotlib_fig_num, total_fig_num)

        for scene, mayavi_fig_num in zip(e.scenes, mayavi_fig_nums):
            current_fig = image_path.format(mayavi_fig_num)
            mlab.savefig(current_fig, figure=scene)
            # make sure the image is not too large
            scale_image(current_fig, current_fig, 850, 999)
            figure_list.append(current_fig)
        mlab.close(all=True)

    return figure_list


Instruction:
Can you generate the documentation for the following Python 3 function
def scale_image(in_fname, out_fname, max_width, max_height):
    # local import to avoid testing dependency on PIL:
    try:
        from PIL import Image
    except ImportError:
        import Image
    img = Image.open(in_fname)
    width_in, height_in = img.size
    scale_w = max_width / float(width_in)
    scale_h = max_height / float(height_in)

    if height_in * scale_w <= max_height:
        scale = scale_w
    else:
        scale = scale_h

    if scale >= 1.0 and in_fname == out_fname:
        return

    width_sc = int(round(scale * width_in))
    height_sc = int(round(scale * height_in))

    # resize the image
    img.thumbnail((width_sc, height_sc), Image.ANTIALIAS)

    # insert centered
    thumb = Image.new('RGB', (max_width, max_height), (255, 255, 255))
    pos_insert = ((max_width - width_sc) // 2, (max_height - height_sc) // 2)
    thumb.paste(img, pos_insert)

    thumb.save(out_fname)
    # Use optipng to perform lossless compression on the resized image if
    # software is installed
    if os.environ.get('SKLEARN_DOC_OPTIPNG', False):
        try:
            subprocess.call(["optipng", "-quiet", "-o", "9", out_fname])
        except Exception:
            warnings.warn('Install optipng to reduce the size of the \
                          generated images')

Response: Scales an image with the same aspect ratio centered in an anonon_image with a given max_width and max_height.


Instruction:
Here you have a function in Python 3, explain what it does
def save_thumbnail(image_path, base_image_name, gallery_conf):
    first_image_file = image_path.format(1)
    thumb_dir = os.path.join(os.path.dirname(first_image_file), 'thumb')
    if not os.path.exists(thumb_dir):
        os.makedirs(thumb_dir)

    thumb_file = os.path.join(thumb_dir,
                              'sphx_glr_%s_thumb.png' % base_image_name)

    if os.path.exists(first_image_file):
        scale_image(first_image_file, thumb_file, 400, 280)
    elif not os.path.exists(thumb_file):
        # create something to replace the thumbnail
        default_thumb_file = os.path.join(glr_path_static(), 'no_image.png')
        default_thumb_file = gallery_conf.get("default_thumb_file",
                                              default_thumb_file)
        scale_image(default_thumb_file, thumb_file, 200, 140)

Response: Save the thumbnail image


Instruction:
Write a Python 3 script to
generate the gallery reStructuredText for an example directory

Response:
def generate_dir_rst(src_dir, target_dir, gallery_conf, seen_backrefs):
    """Generate the gallery reStructuredText for an example directory"""
    if not os.path.exists(os.path.join(src_dir, 'README.txt')):
        print(80 * '_')
        print('Example directory %s does not have a README.txt file' %
              src_dir)
        print('Skipping this directory')
        print(80 * '_')
        return ""  # because string is an expected return type

    fhindex = open(os.path.join(src_dir, 'README.txt')).read()
    if not os.path.exists(target_dir):
        os.makedirs(target_dir)
    sorted_listdir = [fname for fname in sorted(os.listdir(src_dir))
                      if fname.endswith('.py')]
    entries_text = []
    for fname in sorted_listdir:
        amount_of_code = generate_file_rst(fname, target_dir, src_dir,
                                           gallery_conf)
        new_fname = os.path.join(src_dir, fname)
        intro = extract_intro(new_fname)
        write_backreferences(seen_backrefs, gallery_conf,
                             target_dir, fname, intro)
        this_entry = _thumbnail_div(target_dir, fname, intro) + """

.. toctree::
   :hidden:

   /%s/%s\n""" % (target_dir, fname[:-3])
        entries_text.append((amount_of_code, this_entry))

    # sort to have the smallest entries in the beginning
    entries_text.sort()

    for _, entry_text in entries_text:
        fhindex += entry_text

    # clear at the end of the section
    fhindex += """.. raw:: html\n

\n\n"""

    return fhindex


Instruction:
Can you generate the documentation for the following Python 3 function
def execute_script(code_block, example_globals, image_path, fig_count,
                   src_file, gallery_conf):
    """Executes the code block of the example file"""
    time_elapsed = 0
    stdout = ''

    # We need to execute the code
    print('plotting code blocks in %s' % src_file)

    plt.close('all')
    cwd = os.getcwd()
    # Redirect output to stdout and
    orig_stdout = sys.stdout

    try:
        # First cd in the original example dir, so that any file
        # created by the example get created in this directory
        os.chdir(os.path.dirname(src_file))
        my_buffer = StringIO()
        my_stdout = Tee(sys.stdout, my_buffer)
        sys.stdout = my_stdout

        t_start = time()
        exec(code_block, example_globals)
        time_elapsed = time() - t_start

        sys.stdout = orig_stdout

        my_stdout = my_buffer.getvalue().strip().expandtabs()
        if my_stdout:
            stdout = CODE_OUTPUT.format(indent(my_stdout, ' ' * 4))
        os.chdir(cwd)
        figure_list = save_figures(image_path, fig_count, gallery_conf)

        # Depending on whether we have one or more figures, we're using a
        # horizontal list or a single rst call to 'image'.
        image_list = ""
        if len(figure_list) == 1:
            figure_name = figure_list[0]
            image_list = SINGLE_IMAGE % figure_name.lstrip('/')
        elif len(figure_list) > 1:
            image_list = HLIST_HEADER
            for figure_name in figure_list:
                image_list += HLIST_IMAGE_TEMPLATE % figure_name.lstrip('/')

    except Exception:
        formatted_exception = traceback.format_exc()

        print(80 * '_')
        print('%s is not compiling:' % src_file)
        print(formatted_exception)
        print(80 * '_')

        figure_list = []
        image_list = codestr2rst(formatted_exception, lang='pytb')

        # Overrides the output thumbnail in the gallery for easy identification
        broken_img = os.path.join(glr_path_static(), 'broken_example.png')
        shutil.copyfile(broken_img, os.path.join(cwd, image_path.format(1)))
        fig_count += 1  # raise count to avoid overwriting image

        # Breaks build on first example error

        if gallery_conf['abort_on_example_error']:
            raise

    finally:
        os.chdir(cwd)
        sys.stdout = orig_stdout

    print(" - time elapsed : %.2g sec" % time_elapsed)
    code_output = "\n{0}\n\n{1}\n\n".format(image_list, stdout)

    return code_output, time_elapsed, fig_count + len(figure_list)

Response: Executes the code block of the example file and returns a dictionary of the result.


Instruction:
Can you create a Python 3 function that
generates the rst file for a given example.

Response:
def generate_file_rst(fname, target_dir, src_dir, gallery_conf):
    """ Generate the rst file for a given example.

        Returns the amout of code (in characters) of the corresponding
        files.
    """

    src_file = os.path.join(src_dir, fname)
    example_file = os.path.join(target_dir, fname)
    shutil.copyfile(src_file, example_file)

    image_dir = os.path.join(target_dir, 'images')
    if not os.path.exists(image_dir):
        os.makedirs(image_dir)

    base_image_name = os.path.splitext(fname)[0]
    image_fname = 'sphx_glr_' + base_image_name + '_{0:03}.png'
    image_path = os.path.join(image_dir, image_fname)

    script_blocks = split_code_and_text_blocks(example_file)

    amount_of_code = sum([len(bcontent)
                          for blabel, bcontent in script_blocks
                          if blabel == 'code'])

    if _plots_are_current(example_file, image_path):
        return amount_of_code

    time_elapsed = 0

    ref_fname = example_file.replace(os.path.sep, '_')
    example_rst = """\n\n.. _sphx_glr_{0}:\n\n""".format(ref_fname)
    example_nb = Notebook(fname, target_dir)

    filename_pattern = gallery_conf.get('filename_pattern')
    if re.search(filename_pattern, src_file) and gallery_conf['plot_gallery']:
        # A lot of examples contains 'print(__doc__)' for example in
        # scikit-learn so that running the example prints some useful
        # information. Because the docstring has been separated from
        # the code blocks in sphinx-gallery, __doc__ is actually
        # __builtin__.__doc__ in the execution context and we do not
        # want to print it
        example_globals = {'__doc__': ''}
        fig_count = 0
        # A simple example has two blocks: one for the
        # example introduction/explanation and one for the code
        is_example_notebook_like = len(script_blocks) > 2
        for blabel, bcontent in script_blocks:
            if blabel == 'code':
                code_output, rtime, fig_count = execute_script(bcontent,
                                                               example_globals,
                                                               image_path,
                                                               fig_count,
                                                               src_file,
                                                               gallery_conf)

                time_elapsed += rtime
                example_nb.add_code_cell(bcontent)

                if is_example_notebook_like:
                    example_rst += codestr2rst(bcontent) + '\n'
                    example_rst += code_output
                else:
                    example_rst += code_output
                    example_rst += codestr2rst(bcontent) + '\n'

            else:
                example_rst += text2string(bcontent) + '\n'
                example_nb.add_markdown_cell(text2string(bcontent))
    else:
        for blabel, bcontent in script_blocks:
            if blabel == 'code':
                example_rst += codestr2rst(bcontent) + '\n'
                example_nb.add_code_cell(bcontent)
            else:
                example_rst += bcontent + '\n'
                example_nb.add_markdown_cell(text2string(bcontent))

    save_thumbnail(image_path, base_image_name, gallery_conf)

    time_m, time_s = divmod(time_elapsed, 60)
    example_nb.save_file()
    with open(os.path.join(target_dir, base_image_name + '.rst'), 'w') as f:
        example_rst += CODE_DOWNLOAD.format(time_m, time_s, fname,
                                            example_nb.file_name)
        f.write(example_rst)

    return amount_of_code


Instruction:
Can you generate a brief explanation for the following Python 3 code
def _arburg2(X, order):
    x = np.array(X)
    N = len(x)

    if order <= 0.:
        raise ValueError("order must be > 0")

    # Initialisation
    # ------ rho, den
    rho = sum(abs(x)**2.) / N  # Eq 8.21 [Marple]_
    den = rho * 2. * N

    # ------ backward and forward errors
    ef = np.zeros(N, dtype=complex)
    eb = np.zeros(N, dtype=complex)
    for j in range(0, N):  #eq 8.11
        ef[j] = x[j]
        eb[j] = x[j]

    # AR order to be stored
    a = np.zeros(1, dtype=complex)
    a[0] = 1
    # ---- rflection coeff to be stored
    ref = np.zeros(order, dtype=complex)

    temp = 1.
    E = np.zeros(order+1)
    E[0] = rho

    for m in range(0, order):
        #print m
        # Calculate the next order reflection (parcor) coefficient
        efp = ef[1:]
        ebp = eb[0:-1]
        #print efp, ebp
        num = -2.* np.dot(ebp.conj().transpose(),  efp)
        den = np.dot(efp.conj().transpose(),  efp)
        den += np.dot(ebp,  ebp.conj().transpose())
        ref[m] = num / den

        # Update the forward and backward prediction errors
        ef = efp + ref[m] * ebp
        eb = ebp + ref[m].conj().transpose() * efp

        # Update the AR coeff.
        a.resize(len(a)+1)
        a = a + ref[m] * np.flipud(a).conjugate()

        # Update the prediction error
        E[m+1] = (1 - ref[m].conj().transpose()*ref[m]) * E[m]
        #print 'REF', ref, num, den
    return a, E[-1], ref

Response: This version is 10 times faster than arburg but the output rho is not correct.


Instruction:
Can you tell what is the following Python 3 function doing
def arburg(X, order, criteria=None):
    if order <= 0.:
        raise ValueError("order must be > 0")

    if order > len(X):
        raise ValueError("order must be less than length input - 2")

    x = np.array(X)
    N = len(x)

    # Initialisation
    # ------ rho, den
    rho = sum(abs(x)**2.) / float(N)  # Eq 8.21 [Marple]_
    den = rho * 2. * N

    # ---- criteria
    if criteria:
        from spectrum import Criteria
        crit = Criteria(name=criteria, N=N)
        crit.data = rho
        logging.debug('Step {}. old criteria={} new one={}.  rho={}'.format(
                0, crit.old_data, crit.data, rho))

    #p =0
    a = np.zeros(0, dtype=complex)
    ref = np.zeros(0, dtype=complex)
    ef = x.astype(complex)
    eb = x.astype(complex)
    temp = 1.
    #   Main recursion

    for k in range(0, order):

        # calculate the next order reflection coefficient Eq 8.14 Marple
        num = sum([ef[j]*eb[j-1].conjugate() for j in range(k+1, N)])
        den = temp * den - abs(ef[k])**2 - abs(eb[N-1])**2
        kp = -2. * num / den #eq 8.14

        temp = 1. - abs(kp)**2.
        new_rho = temp * rho

        if criteria:
            logging.debug('Step {}. old criteria={} new one={}. rho={}'.format(
                k+1, crit.old_data, crit.data, new_rho))
            #k+1 because order goes from 1 to P whereas k starts at 0.
            status = crit(rho=temp*rho, k=k+1)
            if status is False:
                logging.debug('Stop criteria reached %s %s ' % (crit.data, crit.old_data))
                break
        # this should be after the criteria
        rho = new_rho
        if rho <= 0:
            raise ValueError("Found a negative value (expected positive stricly) %s. Decrease the order" % rho)

        a.resize(a.size+1)
        a[k] = kp
        if k == 0:
            for j in range(N-1, k, -1):
                save2 = ef[j]
                ef[j] = save2 + kp * eb[j-1]          # Eq. (8.7)
                eb[j] = eb[j-1] + kp.conjugate() *  save2

        else:
            # update the AR coeff
            khalf = (k+1)//2  # FIXME here khalf must be an integer
            for j in range(0, khalf):
                ap = a[j] # previous value
                a[j] = ap + kp * a[k-j-1].conjugate()      # Eq. (8.2)
                if j != k-j-1:
                    a[k-j-1] = a[k-j-1] + kp * ap.conjugate()    # Eq. (8.2)

            # update the prediction error
            for j in range(N-1, k, -1):
                save2 = ef[j]
                ef[j] = save2 + kp * eb[j-1]          # Eq. (8.7)
                eb[j] = eb[j-1] + kp.conjugate() *  save2

        # save the reflection coefficient
        ref.resize(ref.size+1)
        ref[k] = kp

    return a, rho, ref

Response: r Estimates the complex autoregressive parameters by the Burg algorithm.


Instruction:
How would you explain what the following Python 3 function does
def _numpy_cholesky(A, B):
    L = numpy.linalg.cholesky(A)
    # A=L*numpy.transpose(L).conjugate()
    # Ly = b
    y = numpy.linalg.solve(L,B)
    # Ux = y
    x = numpy.linalg.solve(L.transpose().conjugate(),y)
    return x, L

Response: Solve Ax = B using numpy cholesky solver


Instruction:
Given the following Python 3 function, write the documentation
def _numpy_solver(A, B):
    x = numpy.linalg.solve(A, B)
    return x

Response:
This function solve Ax = B directly without taking care of the input
    matrix properties.


Instruction:
Here you have a function in Python 3, explain what it does
def CHOLESKY(A, B, method='scipy'):
    if method == 'numpy_solver':
        X = _numpy_solver(A,B)
        return X
    elif method == 'numpy':
        X, _L = _numpy_cholesky(A, B)
        return X
    elif method == 'scipy':
        import scipy.linalg
        L = scipy.linalg.cholesky(A)
        X = scipy.linalg.cho_solve((L, False), B)
    else:
        raise ValueError('method must be numpy_solver, numpy_cholesky or cholesky_inplace')
    return X

Response: Solve linear system Ax = B using CHOLESKY method.


Instruction:
Here you have a function in Python 3, explain what it does
def music(X, IP, NSIG=None, NFFT=default_NFFT, threshold=None, criteria='aic',
        verbose=False):
    """Eigen value pseudo spectrum estimate. See :func:`eigenfre`"""
    return eigen(X, IP, NSIG=NSIG, method='music', NFFT=NFFT,
                 threshold=threshold, criteria=criteria, verbose=verbose)

Response: Eigen value pseudo spectrum estimate. See eigenenfre.


Instruction:
Can you generate the documentation for the following Python 3 function
def eigen(X, P, NSIG=None, method='music', threshold=None, NFFT=default_NFFT,
          criteria='aic', verbose=False):
    r"""Pseudo spectrum using eigenvector method (EV or Music)

    This function computes either the Music or EigenValue (EV) noise
    subspace frequency estimator.

    First, an autocorrelation matrix of order `P` is computed from
    the data. Second, this matrix is separated into vector subspaces,
    one a signal subspace and the other a noise
    subspace using a SVD method to obtain the eigen values and vectors.
    From the eigen values :math:`\lambda_i`, and eigen vectors :math:`v_k`,
    the **pseudo spectrum** (see note below) is computed as follows:

    .. math:: P_{ev}(f) = \frac{1}{e^H(f)\left(\sum\limits_{k=M+1}^{p} \frac{1}{\lambda_k}v_kv_k^H\right)e(f)}

    The separation of the noise and signal subspaces requires expertise
    of the signal. However, AIC and MDL criteria may be used to automatically
    perform this task.

    You still need to provide the parameter `P` to indicate the maximum number
    of eigen values to be computed. The criteria will just select a subset
    to estimate the pseudo spectrum (see :func:`~spectrum.criteria.aic_eigen`
    and :func:`~spectrum.criteria.mdl_eigen` for details.

    .. note:: **pseudo spectrum**. func:`eigen` does not compute a PSD estimate.
        Indeed, the method does not preserve the measured process power.

    :param X: Array data samples
    :param int P: maximum number of eigen values to compute. NSIG (if
        specified) must therefore be less than P.
    :param str method: 'music' or 'ev'.
    :param int NSIG: If specified, the signal sub space uses NSIG eigen values.
    :param float threshold: If specified, the signal sub space is made of the
        eigen values larger than :math:`\rm{threshold} \times \lambda_{min}`,
        where :math:`\lambda_{min}` is the minimum eigen values.
    :param int NFFT: total length of the final data sets (padded with zero
        if needed; default is 4096)

    :return:
        * PSD: Array of real frequency estimator values (two sided for
                complex data and one sided for real data)
        * S, the eigen values

    .. plot::
        :width: 80%
        :include-source:

        from spectrum import eigen, marple_data
        from pylab import plot, log10, linspace, legend, axis

        psd, ev = eigen(marple_data, 15, NSIG=11)
        f = linspace(-0.5, 0.5, len(psd))
        plot(f, 10 * log10(psd/max(psd)), label='User defined')

        psd, ev = eigen(marple_data, 15, threshold=2)
        plot(f, 10 * log10(psd/max(psd)), label='threshold method (100)')

        psd, ev = eigen(marple_data, 15)
        plot(f, 10 * log10(psd/max(psd)), label='AIC method (8)')

        legend()
        axis([-0.5, 0.5, -120, 0])

    .. seealso::
        :func:`pev`,
        :func:`pmusic`,
        :func:`~spectrum.criteria.aic_eigen`

    :References: [Marple]_, Chap 13

    .. todo:: for developers:

        * what should be the second argument of the criteria N, N-P, P...?
        * what should be the max value of NP
    """
    if method not in ['music', 'ev']:
        raise ValueError("method must be 'music' or 'ev'")

    if NSIG != None and threshold != None:
        raise ValueError("NSIG and threshold cannot be provided together")

    if NSIG is not None:
        if NSIG < 0:
            raise ValueError('NSIG must be positive')
        if NSIG >= P:
            raise ValueError("NSIG must be stricly less than IP")

    #
    N = len(X)
    NP = N - P

    assert 2 * NP > P-1, 'decrease the second argument'
    if NP > 100:
        NP = 100

    FB = np.zeros((2*NP, P), dtype=complex)
    #FB = numpy.zeros((MAXU, IP), dtype=complex)
    Z = np.zeros(NFFT, dtype=complex)
    PSD = np.zeros(NFFT)

    # These loops can surely be replaced by a function that create such matrix
    for I in range(0, NP):
        for K in range(0, P):
            FB[I, K] = X[I-K+P-1]
            FB[I+NP, K] = X[I+K+1].conjugate()

    # This commented line produces the correct FB, as the 2 for loops above
    # It is more elegant but slower...corrmtx needs to be optimised (20/4/11)
    #FB2 = spectrum.linalg.corrmtx(X, P-1, method='modified')

    #Compute the eigen values / vectors
    _U, S, V = svd (FB)
    # U and V are not the same as in Marple. Real or Imaginary absolute values
    # are correct but signs are not. This is wierd because the svd function
    # gives the same result as cvsd in Marple. Is FB correct ? it seems so.
    # The following operation has to be done. Otherwise, the resulting PSD is
    # not corect
    V = -V.transpose()

    NSIG  = _get_signal_space(S, 2*NP,
                             verbose=verbose, threshold=threshold,
                             NSIG=NSIG, criteria=criteria)

    #C   AI or Expert Knowledge to choose "signal" singular values, or input
    #C   NSIG at this point
    for I in range(NSIG, P):
        Z[0:P] = V[0:P, I]
        Z[P:NFFT] = 0

        Z  = fft(Z, NFFT)

        if method == 'music':
            PSD = PSD + abs(Z)**2.
        elif method == 'ev' :
            PSD = PSD + abs(Z)**2. / S[I]

    PSD = 1./PSD

    # for some reasons, we need to rearrange the output. this is related to
    # the way U and V are order in the routine svd
    nby2 = int(NFFT/2)

    #return PSD, S

    newpsd = np.append(PSD[nby2:0:-1], PSD[nby2*2-1:nby2-1:-1])
    return newpsd, S

Response: r Computes the pseudo spectrum of the specified method using the specified number of eigen values.


Instruction:
Write a Python 3 function for
getting the signal space from the signal vector S and NP

Response:
def _get_signal_space(S, NP, verbose=False, threshold=None, NSIG=None,
                     criteria='aic'):
    """todo

    """
    from .criteria import aic_eigen, mdl_eigen
    # This section selects automatically the noise and signal subspaces.
    # NSIG being the number of eigenvalues corresponding to signals.
    if NSIG is None:
        if threshold is None:
            logging.debug('computing NSIG using AIC method')
            # get the minimum index of the AIC vector
            if criteria == 'aic':
                aic = aic_eigen(S, NP*2)
            elif criteria == 'mdl':
                aic = mdl_eigen(S, NP*2)
            # get the minimum index of the AIC vector, add 1 to get the NSIG
            NSIG = np.argmin(aic) + 1
            logging.debug('NSIG=', NSIG, ' found as the number of pertinent sinusoids')
        else:
            logging.debug('computing NSIG using user threshold ')
            # following an idea from Matlab, pmusic, we look at the minimum
            # eigen value, and split the eigen values above and below
            # K times min eigen value, where K is >1
            m = threshold * min(S)
            new_s = S[np.where(S>m)]
            NSIG = len(new_s)
            logging.debug('found', NSIG)
            if NSIG == 0:
                NSIG = 1
    return NSIG


Instruction:
Here you have a function in Python 3, explain what it does
def speriodogram(x, NFFT=None, detrend=True, sampling=1.,
                   scale_by_freq=True, window='hamming', axis=0):
    """Simple periodogram, but matrices accepted.

    :param x: an array or matrix of data samples.
    :param NFFT: length of the data before FFT is computed (zero padding)
    :param bool detrend: detrend the data before co,puteing the FFT
    :param float sampling: sampling frequency of the input :attr:`data`.

    :param scale_by_freq:
    :param str window:

    :return: 2-sided PSD if complex data, 1-sided if real.

    if a matrix is provided (using numpy.matrix), then a periodogram
    is computed for each row. The returned matrix has the same shape as the input
    matrix.

    The mean of the input data is also removed from the data before computing
    the psd.

    .. plot::
        :width: 80%
        :include-source:

        from pylab import grid, semilogy
        from spectrum import data_cosine, speriodogram
        data = data_cosine(N=1024, A=0.1, sampling=1024, freq=200)
        semilogy(speriodogram(data, detrend=False, sampling=1024), marker='o')
        grid(True)

    .. plot::
        :width: 80%
        :include-source:

        import numpy
        from spectrum import speriodogram, data_cosine
        from pylab import figure, semilogy, figure ,imshow
        # create N data sets and make the frequency dependent on the time
        N = 100
        m = numpy.concatenate([data_cosine(N=1024, A=0.1, sampling=1024, freq=x)
            for x in range(1, N)]);
        m.resize(N, 1024)
        res = speriodogram(m)
        figure(1)
        semilogy(res)
        figure(2)
        imshow(res.transpose(), aspect='auto')

    .. todo:: a proper spectrogram class/function that takes care of normalisation
    """
    x = np.array(x)
    # array with 1 dimension case
    if x.ndim == 1:
        axis = 0
        r = x.shape[0]
        w = Window(r, window)   #same size as input data
        w = w.data
    # matrix case
    elif x.ndim == 2:
        logging.debug('2D array. each row is a 1D array')
        [r, c] = x.shape
        w = np.array([Window(r, window).data for this in range(c)]).reshape(r,c)

    if NFFT is None:
        NFFT = len(x)

    isreal = np.isrealobj(x)

    if detrend == True:
        m = np.mean(x, axis=axis)
    else:
        m = 0

    if isreal == True:
        if x.ndim == 2:
            res =  (abs (rfft (x*w - m, NFFT, axis=0))) ** 2. / r
        else:
            res =  (abs (rfft (x*w - m, NFFT, axis=-1))) ** 2. / r
    else:
        if x.ndim == 2:
            res =  (abs (fft (x*w - m, NFFT, axis=0))) ** 2. / r
        else:
            res =  (abs (fft (x*w - m, NFFT, axis=-1))) ** 2. / r

    if scale_by_freq is True:
        df = sampling / float(NFFT)
        res*= 2 * np.pi / df

    if x.ndim == 1:
        return res.transpose()
    else:
        return res

Response: Simple periodogram but matrices accepted.


Instruction:
Can you generate the documentation for the following Python 3 function
def WelchPeriodogram(data, NFFT=None,  sampling=1., **kargs):
    from pylab import psd
    spectrum = Spectrum(data, sampling=1.)

    P = psd(data, NFFT, Fs=sampling, **kargs)
    spectrum.psd = P[0]
    #spectrum.__Spectrum_sides = 'twosided'

    return P, spectrum

Response: r This function returns a simple periodogram wrapper of numpy. psd function that calculates the periodogram of the data.


Instruction:
Can you generate the documentation for the following Python 3 function
def DaniellPeriodogram(data, P, NFFT=None, detrend='mean', sampling=1.,
                       scale_by_freq=True, window='hamming'):
    r"""Return Daniell's periodogram.

    To reduce fast fluctuations of the spectrum one idea proposed by daniell
    is to average each value with points in its neighboorhood. It's like
    a low filter.

    .. math:: \hat{P}_D[f_i]= \frac{1}{2P+1} \sum_{n=i-P}^{i+P} \tilde{P}_{xx}[f_n]

    where P is the number of points to average.

    Daniell's periodogram is the convolution of the spectrum with a low filter:

    .. math:: \hat{P}_D(f)=   \hat{P}_{xx}(f)*H(f)

    Example::

        >>> DaniellPeriodogram(data, 8)

    if N/P is not integer, the final values of the original PSD are not used.

    using DaniellPeriodogram(data, 0) should give the original PSD.

    """
    psd = speriodogram(data, NFFT=NFFT, detrend=detrend, sampling=sampling,
                   scale_by_freq=scale_by_freq, window=window)

    if len(psd) % 2 == 1:
        datatype = 'real'
    else:
        datatype = 'complex'

    N = len(psd)
    _slice = 2 * P + 1
    if datatype == 'real': #must get odd value
        newN = np.ceil(psd.size/float(_slice))
        if newN % 2 == 0:
            newN = psd.size/_slice
    else:
        newN = np.ceil(psd.size/float(_slice))
        if newN % 2 == 1:
            newN = psd.size/_slice

    newpsd = np.zeros(int(newN)) # keep integer division
    for i in range(0, newpsd.size):
        count = 0 #needed to know the number of valid averaged values
        for n in range(i*_slice-P, i*_slice+P+1): #+1 to have P values on each sides
            if n > 0 and n<N: #needed to start the average
                count += 1
                newpsd[i] += psd[n]
        newpsd[i] /= float(count)

    #todo: check this
    if datatype == 'complex':
        freq = np.linspace(0, sampling, len(newpsd))
    else:
        df = 1. / sampling
        freq = np.linspace(0,sampling/2., len(newpsd))
    #psd.refreq(2*psd.size()/A.freq());
    #psd.retime(-1./psd.freq()+1./A.size());

    return newpsd, freq

Response: r Return the Daniell s periodogram.


Instruction:
Can you write a function in Python 3 where it
returns the centered frequency range as a generator.

Response:
def centerdc_gen(self):
        """Return the centered frequency range as a generator.

        ::

            >>> print(list(Range(8).centerdc_gen()))
            [-0.5, -0.375, -0.25, -0.125, 0.0, 0.125, 0.25, 0.375]

        """
        for a in range(0, self.N):
            yield (a-self.N/2) * self.df


Instruction:
How would you code a function in Python 3 to
return the one - sided frequency range as a generator.

Response:
def onesided_gen(self):
        """Return the one-sided frequency range as a generator.

        If :attr:`N` is even, the length is N/2 + 1.
        If :attr:`N` is odd, the length is (N+1)/2.

        ::

            >>> print(list(Range(8).onesided()))
            [0.0, 0.125, 0.25, 0.375, 0.5]
            >>> print(list(Range(9).onesided()))
            [0.0, 0.1111, 0.2222, 0.3333, 0.4444]

        """
        if self.N % 2 == 0:
            for n in range(0, self.N//2 + 1):
                yield n * self.df
        else:
            for n in range(0, (self.N+1)//2):
                yield n * self.df


Instruction:
How would you implement a function in Python 3 that
returns the frequency vector according to the given sides.

Response:
def frequencies(self, sides=None):

        """Return the frequency vector according to :attr:`sides`"""
        # use the attribute sides except if a valid sides argument is provided
        if sides is None:
            sides = self.sides
        if sides not in self._sides_choices:
            raise errors.SpectrumChoiceError(sides, self._sides_choices)

        if sides == 'onesided':
            return self._range.onesided()
        if sides == 'twosided':
            return self._range.twosided()
        if sides == 'centerdc':
            return self._range.centerdc()


Instruction:
Can you tell what is the following Python 3 function doing
def get_converted_psd(self, sides):
        if sides == self.sides:
            #nothing to be done is sides = :attr:`sides
            return self.__psd

        if self.datatype == 'complex':
            assert sides != 'onesided', \
                "complex datatype so sides cannot be onesided."

        if self.sides == 'onesided':
            logging.debug('Current sides is onesided')
            if sides == 'twosided':
                logging.debug('--->Converting to twosided')
                # here we divide everything by 2 to get the twosided version
                #N = self.NFFT
                newpsd = numpy.concatenate((self.psd[0:-1]/2., list(reversed(self.psd[0:-1]/2.))))
                # so we need to multiply by 2 the 0 and FS/2 frequencies
                newpsd[-1] = self.psd[-1]
                newpsd[0] *= 2.
            elif sides == 'centerdc':
                # FIXME. this assumes data is even so PSD is stored as
                # P0 X1 X2 X3 P1
                logging.debug('--->Converting to centerdc')
                P0 = self.psd[0]
                P1 = self.psd[-1]
                newpsd = numpy.concatenate((self.psd[-1:0:-1]/2., self.psd[0:-1]/2.))
                # so we need to multiply by 2 the 0 and F2/2 frequencies
                #newpsd[-1] = P0 / 2
                newpsd[0] = P1
        elif self.sides == 'twosided':
            logging.debug('Current sides is twosided')
            if sides == 'onesided':
                # we assume that data is stored as X0,X1,X2,X3,XN
                # that is original data is even.
                logging.debug('Converting to onesided assuming ori data is even')
                midN = (len(self.psd)-2) / 2
                newpsd = numpy.array(self.psd[0:int(midN)+2]*2)
                newpsd[0] /= 2
                newpsd[-1] = self.psd[-1]
            elif sides == 'centerdc':
                newpsd = stools.twosided_2_centerdc(self.psd)
        elif self.sides == 'centerdc': # same as twosided to onesided
            logging.debug('Current sides is centerdc')
            if sides == 'onesided':
                logging.debug('--->Converting to onesided')
                midN = int(len(self.psd) / 2)
                P1 = self.psd[0]
                newpsd = numpy.append(self.psd[midN:]*2, P1)
            elif sides == 'twosided':
                newpsd = stools.centerdc_2_twosided(self.psd)
        else:
            raise ValueError("sides must be set to 'onesided', 'twosided' or 'centerdc'")

        return newpsd

Response: This function returns the PSD in the given sides format in the onesided twosided or centerdc format.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def plot(self, filename=None, norm=False, ylim=None,
              sides=None,  **kargs):
        """a simple plotting routine to plot the PSD versus frequency.

        :param str filename: save the figure into a file
        :param norm: False by default. If True, the PSD is normalised.
        :param ylim: readjust the y range .
        :param sides: if not provided, :attr:`sides` is used. See :attr:`sides`
            for details.
        :param kargs: any optional argument accepted by :func:`pylab.plot`.

        .. plot::
            :width: 80%
            :include-source:

            from spectrum import *
            p = Periodogram(marple_data)
            p.plot(norm=True, marker='o')

        """
        import pylab
        from pylab import ylim as plt_ylim
        #First, check that psd attribute is up-to-date
        # just to get the PSD to be recomputed if needed
        _ = self.psd

        # check that the input sides parameter is correct if provided
        if sides is not None:
            if sides not in self._sides_choices:
                raise errors.SpectrumChoiceError(sides, self._sides_choices)

        # if sides is provided but identical to the current psd, nothing to do.
        # if sides not provided, let us use self.sides
        if sides is None or sides == self.sides:
            frequencies = self.frequencies()
            psd = self.psd
            sides = self.sides
        elif sides is not None:
            # if sides argument is different from the attribute, we need to
            # create a new PSD/Freq ; indeed we do not want to change the
            # attribute itself

            # if data is complex, one-sided is wrong in any case.
            if self.datatype == 'complex':
                if sides == 'onesided':
                    raise ValueError("sides cannot be one-sided with complex data")

            logging.debug("sides is different from the one provided. Converting PSD")
            frequencies = self.frequencies(sides=sides)
            psd = self.get_converted_psd(sides)

        if len(psd) != len(frequencies):
            raise ValueError("PSD length is %s and freq length is %s" % (len(psd), len(frequencies)))

        if 'ax' in list(kargs.keys()):
            save_ax = pylab.gca()
            pylab.sca(kargs['ax'])
            rollback = True
            del kargs['ax']
        else:
            rollback = False

        if norm:
            pylab.plot(frequencies, 10 * stools.log10(psd/max(psd)),  **kargs)
        else:
            pylab.plot(frequencies, 10 * stools.log10(psd),**kargs)

        pylab.xlabel('Frequency')
        pylab.ylabel('Power (dB)')
        pylab.grid(True)

        if ylim:
            plt_ylim(ylim)

        if sides == 'onesided':
            pylab.xlim(0, self.sampling/2.)
        elif sides == 'twosided':
            pylab.xlim(0, self.sampling)
        elif sides == 'centerdc':
            pylab.xlim(-self.sampling/2., self.sampling/2.)

        if filename:
            pylab.savefig(filename)

        if rollback:
            pylab.sca(save_ax)

        del psd, frequencies

Response: a simple plotting routine to plot the PSD versus frequency.


Instruction:
Given the following Python 3 function, write the documentation
def ipy_notebook_skeleton():
    py_version = sys.version_info
    notebook_skeleton = {
        "cells": [],
        "metadata": {
            "kernelspec": {
                "display_name": "Python " + str(py_version[0]),
                "language": "python",
                "name": "python" + str(py_version[0])
            },
            "language_info": {
                "codemirror_mode": {
                    "name": "ipython",
                    "version": py_version[0]
                },
                "file_extension": ".py",
                "mimetype": "text/x-python",
                "name": "python",
                "nbconvert_exporter": "python",
                "pygments_lexer": "ipython" + str(py_version[0]),
                "version": '{0}.{1}.{2}'.format(*sys.version_info[:3])
            }
        },
        "nbformat": 4,
        "nbformat_minor": 0
    }
    return notebook_skeleton

Response: Returns a dictionary with the elements of a Jupyter notebook that are in IPython notebook format.


Instruction:
Make a summary of the following Python 3 code
def rst2md(text):

    top_heading = re.compile(r'^=+$\s^([\w\s-]+)^=+$', flags=re.M)
    text = re.sub(top_heading, r'# \1', text)

    math_eq = re.compile(r'^\.\. math::((?:.+)?(?:\n+^  .+)*)', flags=re.M)
    text = re.sub(math_eq,
                  lambda match: r'$${0}$$'.format(match.group(1).strip()),
                  text)
    inline_math = re.compile(r':math:`(.+)`')
    text = re.sub(inline_math, r'$\1$', text)

    return text

Response:
Converts the RST text from the examples docstrigs and comments
    into markdown text for IPython Notebooks


Instruction:
Make a summary of the following Python 3 code
def add_markdown_cell(self, text):
        markdown_cell = {
            "cell_type": "markdown",
            "metadata": {},
            "source": [rst2md(text)]
        }
        self.work_notebook["cells"].append(markdown_cell)

Response: Add a markdown cell to the notebook


Instruction:
How would you code a function in Python 3 to
save the notebook to a file

Response:
def save_file(self):
        """Saves the notebook to a file"""
        with open(self.write_file, 'w') as out_nb:
            json.dump(self.work_notebook, out_nb, indent=2)


Instruction:
Can you tell what is the following Python 3 function doing
def arma2psd(A=None, B=None, rho=1., T=1., NFFT=4096, sides='default',
        norm=False):
    r"""Computes power spectral density given ARMA values.

    This function computes the power spectral density values
    given the ARMA parameters of an ARMA model. It assumes that
    the driving sequence is a white noise process of zero mean and
    variance :math:`\rho_w`. The sampling frequency and noise variance are
    used to scale the PSD output, which length is set by the user with the
    `NFFT` parameter.

    :param array A:   Array of AR parameters (complex or real)
    :param array B:   Array of MA parameters (complex or real)
    :param float rho: White noise variance to scale the returned PSD
    :param float T:   Sample interval in seconds to scale the returned PSD
    :param int NFFT:  Final size of the PSD
    :param str sides: Default PSD is two-sided, but sides can be set to centerdc.

    .. warning:: By convention, the AR or MA arrays does not contain the
        A0=1 value.

    If :attr:`B` is None, the model is a pure AR model. If :attr:`A` is None,
    the model is a pure MA model.

    :return: two-sided PSD

    .. rubric:: Details:

    AR case: the power spectral density is:

    .. math:: P_{ARMA}(f) = T \rho_w \left|\frac{B(f)}{A(f)}\right|^2

    where:

    .. math:: A(f) = 1 + \sum_{k=1}^q b(k) e^{-j2\pi fkT}
    .. math:: B(f) = 1 + \sum_{k=1}^p a(k) e^{-j2\pi fkT}

    .. rubric:: **Example:**

    .. plot::
        :width: 80%
        :include-source:

        import spectrum.arma
        from pylab import plot, log10, legend
        plot(10*log10(spectrum.arma.arma2psd([1,0.5],[0.5,0.5])), label='ARMA(2,2)')
        plot(10*log10(spectrum.arma.arma2psd([1,0.5],None)), label='AR(2)')
        plot(10*log10(spectrum.arma.arma2psd(None,[0.5,0.5])), label='MA(2)')
        legend()

    :References: [Marple]_
    """
    if NFFT is None:
        NFFT = 4096

    if A is None and B is None:
        raise ValueError("Either AR or MA model must be provided")

    psd = np.zeros(NFFT, dtype=complex)

    if A is not None:
        ip = len(A)
        den = np.zeros(NFFT, dtype=complex)
        den[0] = 1.+0j
        for k in range(0, ip):
            den[k+1] = A[k]
        denf = fft(den, NFFT)

    if B is not None:
        iq = len(B)
        num = np.zeros(NFFT, dtype=complex)
        num[0] = 1.+0j
        for k in range(0, iq):
            num[k+1] = B[k]
        numf = fft(num, NFFT)

    # Changed in version 0.6.9 (divided by T instead of multiply)
    if A is not None and B is not None:
        psd = rho / T * abs(numf)**2. / abs(denf)**2.
    elif A is not None:
        psd = rho / T / abs(denf)**2.
    elif B is not None:
        psd = rho / T * abs(numf)**2.

    psd = np.real(psd)
    # The PSD is a twosided PSD.
    # to obtain the centerdc
    if sides != 'default':
        from . import tools
        assert sides in ['centerdc']
        if sides == 'centerdc':
            psd = tools.twosided_2_centerdc(psd)

    if norm == True:
        psd /= max(psd)

    return psd

Response: r Calculates the power spectral density of the given ARMA parameters.


Instruction:
Explain what the following Python 3 code does
def ma(X, Q, M):
    if Q <= 0 or Q >= M:
        raise ValueError('Q(MA) must be in ]0,lag[')

    #C   Fit a high-order AR to the data
    a, rho, _c = yulewalker.aryule(X, M, 'biased')   #! Eq. (10.5)

    #add an element unity to the AR parameter array
    a = np.insert(a, 0, 1)

    #C   Find MA parameters from autocorrelations by Yule-Walker method
    ma_params, _p, _c = yulewalker.aryule(a, Q, 'biased')    #! Eq. (10.7)

    return ma_params, rho

Response:
Moving average estimator.

    This program provides an estimate of the moving average parameters
    and driving noise variance for a data sequence based on a
    long AR model and a least squares fit.

    :param array X: The input data array
    :param int Q: Desired MA model order (must be >0 and <M)
    :param int M: Order of "long" AR model (suggest at least 2*Q )

    :return:
        * MA    - Array of Q complex MA parameter estimates
        * RHO   - Real scalar of white noise variance estimate

    .. plot::
        :width: 80%
        :include-source:

        from spectrum import arma2psd, ma, marple_data
        import pylab

        # Estimate 15 Ma parameters
        b, rho = ma(marple_data, 15, 30)
        # Create the PSD from those MA parameters
        psd = arma2psd(B=b, rho=rho, sides='centerdc')
        # and finally plot the PSD
        pylab.plot(pylab.linspace(-0.5, 0.5, 4096), 10 * pylab.log10(psd/max(psd)))
        pylab.axis([-0.5, 0.5, -30, 0])

    :reference: [Marple]_


Instruction:
Can you create a Python 3 function that
computes the cross PSD estimate using the correlogram method.

Response:
def CORRELOGRAMPSD(X, Y=None, lag=-1, window='hamming',
                    norm='unbiased', NFFT=4096, window_params={},
                    correlation_method='xcorr'):
    """PSD estimate using correlogram method.

    :param array X: complex or real data samples X(1) to X(N)
    :param array Y: complex data samples Y(1) to Y(N). If provided, computes
        the cross PSD, otherwise the PSD is returned
    :param int lag: highest lag index to compute. Must be less than N
    :param str window_name: see :mod:`window` for list of valid names
    :param str norm: one of the valid normalisation of :func:`xcorr` (biased,
        unbiased, coeff, None)
    :param int NFFT: total length of the final data sets (padded with zero
        if needed; default is 4096)
    :param str correlation_method: either `xcorr` or `CORRELATION`.
        CORRELATION should be removed in the future.

    :return:
        * Array of real (cross) power spectral density estimate values. This is
          a two sided array with negative values following the positive ones
          whatever is the input data (real or complex).

    .. rubric:: Description:

    The exact power spectral density is the Fourier transform of the
    autocorrelation sequence:

    .. math:: P_{xx}(f) = T \sum_{m=-\infty}^{\infty} r_{xx}[m] exp^{-j2\pi fmT}

    The correlogram method of PSD estimation substitutes a finite sequence of
    autocorrelation estimates :math:`\hat{r}_{xx}` in place of :math:`r_{xx}`.
    This estimation can be computed with :func:`xcorr` or :func:`CORRELATION` by
    chosing a proprer lag `L`. The estimated PSD is then

    .. math:: \hat{P}_{xx}(f) = T \sum_{m=-L}^{L} \hat{r}_{xx}[m] exp^{-j2\pi fmT}

    The lag index must be less than the number of data samples `N`. Ideally, it
    should be around `L/10` [Marple]_ so as to avoid greater statistical
    variance associated with higher lags.

    To reduce the leakage of the implicit rectangular window and therefore to
    reduce the bias in the estimate, a tapering window is normally used and lead
    to the so-called Blackman and Tukey correlogram:

    .. math:: \hat{P}_{BT}(f) = T \sum_{m=-L}^{L} w[m] \hat{r}_{xx}[m] exp^{-j2\pi fmT}

    The correlogram for the cross power spectral estimate is

    .. math:: \hat{P}_{xx}(f) = T \sum_{m=-L}^{L} \hat{r}_{xx}[m] exp^{-j2\pi fmT}

    which is computed if :attr:`Y` is not provide. In such case,
    :math:`r_{yx} = r_{xy}` so we compute the correlation only once.

    .. plot::
        :width: 80%
        :include-source:

        from spectrum import CORRELOGRAMPSD, marple_data
        from spectrum.tools import cshift
        from pylab import log10, axis, grid, plot,linspace

        psd = CORRELOGRAMPSD(marple_data, marple_data, lag=15)
        f = linspace(-0.5, 0.5, len(psd))
        psd = cshift(psd, len(psd)/2)
        plot(f, 10*log10(psd/max(psd)))
        axis([-0.5,0.5,-50,0])
        grid(True)

    .. seealso:: :func:`create_window`, :func:`CORRELATION`, :func:`xcorr`,
        :class:`pcorrelogram`.
    """
    N = len(X)
    assert lag<N, 'lag must be < size of input data'
    assert correlation_method in ['CORRELATION', 'xcorr']
    if Y is None:
        Y = numpy.array(X)
        crosscorrelation = False
    else:
        crosscorrelation = True

    if NFFT is None:
        NFFT = N
    psd = numpy.zeros(NFFT, dtype=complex)

    # Window should be centered around zero. Moreover, we want only the
    # positive values. So, we need to use 2*lag + 1 window and keep values on
    # the right side.
    w = Window(2.*lag+1, window, **window_params)
    w = w.data[lag+1:]

    # compute the cross correlation
    if correlation_method == 'CORRELATION':
        rxy = CORRELATION (X, Y, maxlags=lag, norm=norm)
    elif correlation_method == 'xcorr':
        rxy, _l = xcorr (X, Y, maxlags=lag, norm=norm)
        rxy = rxy[lag:]

    # keep track of the first elt.
    psd[0] = rxy[0]

    # create the first part of the PSD
    psd[1:lag+1] = rxy[1:] * w

    # create the second part.
    # First, we need to compute the auto or cross correlation ryx
    if crosscorrelation is True:
        # compute the cross correlation
        if correlation_method == 'CORRELATION':
            ryx = CORRELATION(Y, X, maxlags=lag, norm=norm)
        elif correlation_method == 'xcorr':
            ryx, _l = xcorr(Y, X, maxlags=lag, norm=norm)
            ryx = ryx[lag:]
        #print len(ryx), len(psd[-1:NPSD-lag-1:-1])

        psd[-1:NFFT-lag-1:-1] = ryx[1:].conjugate() * w
    else: #autocorrelation no additional correlation call required
        psd[-1:NFFT-lag-1:-1] = rxy[1:].conjugate() * w

    psd = numpy.real(fft(psd))

    return psd


Instruction:
Can you tell what is the following Python 3 function doing
def _select_block(str_in, start_tag, end_tag):
    start_pos = str_in.find(start_tag)
    if start_pos < 0:
        raise ValueError('start_tag not found')
    depth = 0
    for pos in range(start_pos, len(str_in)):
        if str_in[pos] == start_tag:
            depth += 1
        elif str_in[pos] == end_tag:
            depth -= 1

        if depth == 0:
            break
    sel = str_in[start_pos + 1:pos]
    return sel

Response: Select first block delimited by start_tag and end_tag


Instruction:
Can you create a Python 3 function that
parses a dictionary from the search index

Response:
def _parse_dict_recursive(dict_str):
    """Parse a dictionary from the search index"""
    dict_out = dict()
    pos_last = 0
    pos = dict_str.find(':')
    while pos >= 0:
        key = dict_str[pos_last:pos]
        if dict_str[pos + 1] == '[':
            # value is a list
            pos_tmp = dict_str.find(']', pos + 1)
            if pos_tmp < 0:
                raise RuntimeError('error when parsing dict')
            value = dict_str[pos + 2: pos_tmp].split(',')
            # try to convert elements to int
            for i in range(len(value)):
                try:
                    value[i] = int(value[i])
                except ValueError:
                    pass
        elif dict_str[pos + 1] == '{':
            # value is another dictionary
            subdict_str = _select_block(dict_str[pos:], '{', '}')
            value = _parse_dict_recursive(subdict_str)
            pos_tmp = pos + len(subdict_str)
        else:
            raise ValueError('error when parsing dict: unknown elem')

        key = key.strip('"')
        if len(key) > 0:
            dict_out[key] = value

        pos_last = dict_str.find(',', pos_tmp)
        if pos_last < 0:
            break
        pos_last += 1
        pos = dict_str.find(':', pos_last)

    return dict_out


Instruction:
Explain what the following Python 3 code does
def parse_sphinx_searchindex(searchindex):
    # Make sure searchindex uses UTF-8 encoding
    if hasattr(searchindex, 'decode'):
        searchindex = searchindex.decode('UTF-8')

    # parse objects
    query = 'objects:'
    pos = searchindex.find(query)
    if pos < 0:
        raise ValueError('"objects:" not found in search index')

    sel = _select_block(searchindex[pos:], '{', '}')
    objects = _parse_dict_recursive(sel)

    # parse filenames
    query = 'filenames:'
    pos = searchindex.find(query)
    if pos < 0:
        raise ValueError('"filenames:" not found in search index')
    filenames = searchindex[pos + len(query) + 1:]
    filenames = filenames[:filenames.find(']')]
    filenames = [f.strip('"') for f in filenames.split(',')]

    return filenames, objects

Response: Parse a Sphinx search index and return a list of filenames and objects.


Instruction:
Implement a Python 3 function for
embedding hyperlinks to documentation into example code

Response:
def embed_code_links(app, exception):
    """Embed hyperlinks to documentation into example code"""
    if exception is not None:
        return

    # No need to waste time embedding hyperlinks when not running the examples
    # XXX: also at the time of writing this fixes make html-noplot
    # for some reason I don't fully understand
    if not app.builder.config.plot_gallery:
        return

    # XXX: Whitelist of builders for which it makes sense to embed
    # hyperlinks inside the example html. Note that the link embedding
    # require searchindex.js to exist for the links to the local doc
    # and there does not seem to be a good way of knowing which
    # builders creates a searchindex.js.
    if app.builder.name not in ['html', 'readthedocs']:
        return

    print('Embedding documentation hyperlinks in examples..')

    gallery_conf = app.config.sphinx_gallery_conf

    gallery_dirs = gallery_conf['gallery_dirs']
    if not isinstance(gallery_dirs, list):
        gallery_dirs = [gallery_dirs]

    for gallery_dir in gallery_dirs:
        _embed_code_links(app, gallery_conf, gallery_dir)


Instruction:
Can you generate a brief explanation for the following Python 3 code
def _get_link(self, cobj):

        fname_idx = None
        full_name = cobj['module_short'] + '.' + cobj['name']
        if full_name in self._searchindex['objects']:
            value = self._searchindex['objects'][full_name]
            if isinstance(value, dict):
                value = value[next(iter(value.keys()))]
            fname_idx = value[0]
        elif cobj['module_short'] in self._searchindex['objects']:
            value = self._searchindex['objects'][cobj['module_short']]
            if cobj['name'] in value.keys():
                fname_idx = value[cobj['name']][0]

        if fname_idx is not None:
            fname = self._searchindex['filenames'][fname_idx] + '.html'

            if self._is_windows:
                fname = fname.replace('/', '\\')
                link = os.path.join(self.doc_url, fname)
            else:
                link = posixpath.join(self.doc_url, fname)

            if hasattr(link, 'decode'):
                link = link.decode('utf-8', 'replace')

            if link in self._page_cache:
                html = self._page_cache[link]
            else:
                html = get_data(link, self.gallery_dir)
                self._page_cache[link] = html

            # test if cobj appears in page
            comb_names = [cobj['module_short'] + '.' + cobj['name']]
            if self.extra_modules_test is not None:
                for mod in self.extra_modules_test:
                    comb_names.append(mod + '.' + cobj['name'])
            url = False
            if hasattr(html, 'decode'):
                # Decode bytes under Python 3
                html = html.decode('utf-8', 'replace')

            for comb_name in comb_names:
                if hasattr(comb_name, 'decode'):
                    # Decode bytes under Python 3
                    comb_name = comb_name.decode('utf-8', 'replace')
                if comb_name in html:
                    url = link + u'#' + comb_name
            link = url
        else:
            link = False

        return link

Response: Get a valid link for the object cobj.


Instruction:
Can you tell what is the following Python 3 function doing
def create_all_psd():

    f = pylab.linspace(0, 1, 4096)

    pylab.figure(figsize=(12,8))

    # MA model
    p = spectrum.pma(xx, 64,128); p(); p.plot()
    """
    #ARMA 15 order
    a, b, rho = spectrum.arma_estimate(data, 15,15, 30)
    psd = spectrum.arma2psd(A=a,B=b, rho=rho)
    newpsd = tools.cshift(psd, len(psd)//2) # switch positive and negative freq
    pylab.plot(f, 10 * pylab.log10(newpsd/max(newpsd)), label='ARMA 15,15')
    """
    # YULE WALKER
    p = spectrum.pyule(xx, 7 , NFFT=4096, scale_by_freq=False); p.plot()
    # equivalent to
    # plot([x for x in p.frequencies()] , 10*log10(p.psd)); grid(True)

    #burg method
    p = spectrum.pburg(xx, 7, scale_by_freq=False);  p.plot()

    #pcovar
    p = spectrum.pcovar(xx, 7, scale_by_freq=False);  p.plot()

    #pmodcovar
    p = spectrum.pmodcovar(xx, 7, scale_by_freq=False); p.plot()

    # correlogram
    p = spectrum.pcorrelogram(xx, lag=60, NFFT=512, scale_by_freq=False); p.plot()

    # minvar
    p = spectrum.pminvar(xx, 7, NFFT=256, scale_by_freq=False); p.plot()

    # pmusic
    p = spectrum.pmusic(xx, 10,4, scale_by_freq=False); p.plot()

    # pmusic
    p = spectrum.pev(xx, 10, 4, scale_by_freq=False); p.plot()

    # periodogram
    p = spectrum.Periodogram(xx, scale_by_freq=False); p.plot()

    #
    legend( ["MA 32", "pyule 7", "pburg 7", "pcovar", "pmodcovar", "correlogram",
                "minvar", "pmusic", "pev", "periodgram"])

    pylab.ylim([-80,80])

Response: Create all the PSDs for all the data points.


Instruction:
Can you generate the documentation for the following Python 3 function
def tf2zp(b,a):
    from numpy import roots
    assert len(b) == len(a), "length of the vectors a and b must be identical. fill with zeros if needed."

    g = b[0] / a[0]
    z = roots(b)
    p = roots(a)

    return z, p, g

Response: Convert a two - dimensional array of transfer function filter parameters to zero - pole - gain form.


Instruction:
How would you implement a function in Python 3 that
gives two list or arrays pad with zeros the shortest array

Response:
def eqtflength(b,a):
    """Given two list or arrays, pad with zeros the shortest array

    :param b: list or array
    :param a: list or array

    .. doctest::

        >>> from spectrum.transfer import eqtflength
        >>> a = [1,2]
        >>> b = [1,2,3,4]
        >>> a, b, = eqtflength(a,b)

    """
    d = abs(len(b)-len(a))
    if d != 0:
        if len(a) > len(b):
            try:
                b.extend([0.]*d)
            except:
                b = np.append(b, [0]*d)
        elif len(b)>len(a):
            try:
                a.extend([0.]*d)
            except:
                a = np.append(a, [0]*d)
        return b,a
    else:
        return b,a


Instruction:
How would you code a function in Python 3 to
convert a numerator polynomial to zero - pole - gain filter parameter form a numerator polynomial.

Response:
def tf2zpk(b, a):
    """Return zero, pole, gain (z,p,k) representation from a numerator,
    denominator representation of a linear filter.

    Convert zero-pole-gain filter parameters to transfer function form

    :param ndarray b:  numerator polynomial.
    :param ndarray a: numerator and denominator polynomials.

    :return:
        * z : ndarray        Zeros of the transfer function.
        * p : ndarray        Poles of the transfer function.
        * k : float        System gain.

    If some values of b are too close to 0, they are removed. In that case, a
    BadCoefficients warning is emitted.

    .. doctest::

        >>> import scipy.signal
        >>> from spectrum.transfer import tf2zpk
        >>> [b, a] = scipy.signal.butter(3.,.4)
        >>> z, p ,k = tf2zpk(b,a)

    .. seealso:: :func:`zpk2tf`
    .. note:: wrapper of scipy function tf2zpk
    """
    import scipy.signal
    z,p,k = scipy.signal.tf2zpk(b, a)
    return z,p,k


Instruction:
Make a summary of the following Python 3 code
def ss2zpk(a,b,c,d, input=0):
    import scipy.signal
    z, p, k = scipy.signal.ss2zpk(a, b, c, d, input=input)
    return z, p, k

Response: State - space representation to zero - pole - gain representation.


Instruction:
Make a summary of the following Python 3 code
def zpk2tf(z, p, k):
    import scipy.signal
    b, a = scipy.signal.zpk2tf(z, p, k)
    return b, a

Response: r Return polynomial transfer function representation from zeros poles and gains of each numerator transfer function.


Instruction:
Write a Python 3 function for
zeroing - pole - gain representation to state - space representation

Response:
def zpk2ss(z, p, k):
    """Zero-pole-gain representation to state-space representation

    :param sequence z,p: Zeros and poles.
    :param float k: System gain.

    :return:
        * A, B, C, D : ndarray State-space matrices.

    .. note:: wrapper of scipy function zpk2ss
    """
    import scipy.signal
    return scipy.signal.zpk2ss(z,p,k)


Instruction:
Can you tell what is the following Python 3 function doing
def create_window(N, name=None, **kargs):
    if name is None:
        name = 'rectangle'
    name = name.lower()
    assert name in list(window_names.keys()), \
        """window name %s not implemented or incorrect. Try to use one of %s"""\
        % (name, window_names)

    # create the function name
    f = eval(window_names[name])

    windows_with_parameters = \
    {'kaiser': {'beta': eval(window_names['kaiser']).__defaults__[0]},
     'blackman': {'alpha': eval(window_names['blackman']).__defaults__[0]},
     'cauchy': {'alpha': eval(window_names['cauchy']).__defaults__[0]},
     'flattop': {'mode': eval(window_names['flattop']).__defaults__[0]},
     'gaussian': {'alpha': eval(window_names['gaussian']).__defaults__[0]},
     'chebwin': {'attenuation':eval(window_names['chebwin']).__defaults__[0]},
     'tukey': {'r':eval(window_names['tukey']).__defaults__[0]},
     'poisson': {'alpha': eval(window_names['poisson']).__defaults__[0]},
     'poisson_hanning': {'alpha':
                         eval(window_names['poisson_hanning']).__defaults__[0]},
     'taylor': {'nbar': eval(window_names['taylor']).__defaults__[0],
                'sll': eval(window_names['taylor']).__defaults__[0]},
    }

    if name not in list(windows_with_parameters.keys()):
        if len(kargs) == 0:
            # no parameters, so we directly call the function
            w = f(N)
        else:
            raise ValueError("""
            Parameters do not match any of the window. The window provided
            do not expect any parameters. Try to remove the parameters""")
    elif name in list(windows_with_parameters.keys()):
        # user optional parameters are provided, scan them:
        dargs = {}
        for arg in list(kargs.keys()):
            # check that the parameters are valid, and obtain the default value
            try:
                default = windows_with_parameters[name][arg]
            except:
                raise ValueError("""
                    Invalid optional argument (%s) for %s window.
                    Valid optional arguments are (%s)""" % \
                    (arg, name, list(windows_with_parameters[name].keys())))
            # add the user parameter to the list of parameters
            dargs[arg] = kargs.get(arg, default)
        # call the proper function with the optional arguments
        w = f(N, **dargs)

    return w

Response: r Returns a N - point window given a valid name.


Instruction:
Here you have a function in Python 3, explain what it does
def _kaiser(n, beta):
    from scipy.special import iv as besselI
    m = n - 1
    k = arange(0, m)
    k = 2. * beta / m * sqrt (k * (m - k))
    w = besselI (0, k) / besselI (0, beta)
    return w

Response:
Independant Kaiser window

    For the definition of the Kaiser window, see A. V. Oppenheim & R. W. Schafer, "Discrete-Time Signal Processing".

    The continuous version of width n centered about x=0 is:

    .. note:: 2 times slower than scipy.kaiser


Instruction:
Given the following Python 3 function, write the documentation
def window_kaiser(N, beta=8.6, method='numpy'):
    if N == 1:
        return ones(1)
    if method == 'numpy':
        from numpy import kaiser
        return kaiser(N, beta)
    else:
        return _kaiser(N, beta)

Response: r A function that returns a Kaiser window with the given length and a given Bessel function.


Instruction:
Can you generate the documentation for the following Python 3 function
def window_blackman(N, alpha=0.16):
    a0 = (1. - alpha)/2.
    a1 = 0.5
    a2 = alpha/2.

    if (N == 1):
        win = array([1.])
    else:
        k = arange(0, N)/float(N-1.)
        win =  a0 - a1 * cos (2 * pi * k) + a2 * cos (4 * pi * k)
    return win

Response: r Blackman window with N elements.


Instruction:
Given the following Python 3 function, write the documentation
def window_chebwin(N, attenuation=50):
    import scipy.signal
    return scipy.signal.chebwin(N, attenuation)

Response:
Cheb window

    :param N: window length

    .. plot::
        :width: 80%
        :include-source:

        from spectrum import window_visu
        window_visu(64, 'chebwin', attenuation=50)

    .. seealso:: scipy.signal.chebwin, :func:`create_window`, :class:`Window`


Instruction:
How would you explain what the following Python 3 function does
def window_lanczos(N):
    if N ==1:
        return ones(1)

    n = linspace(-N/2., N/2., N)
    win = sinc(2*n/(N-1.))
    return win

Response: Lanczos window also known as sinc window.


Instruction:
Make a summary of the following Python 3 code
def window_nuttall(N):
    a0 = 0.355768
    a1 = 0.487396
    a2 = 0.144232
    a3 = 0.012604

    return _coeff4(N, a0, a1, a2, a3)

Response:
r"""Nuttall tapering window

    :param N: window length

    .. math:: w(n) = a_0 - a_1 \cos\left(\frac{2\pi n}{N-1}\right)+ a_2 \cos\left(\frac{4\pi n}{N-1}\right)- a_3 \cos\left(\frac{6\pi n}{N-1}\right)

    with :math:`a_0 = 0.355768`, :math:`a_1 = 0.487396`, :math:`a_2=0.144232` and :math:`a_3=0.012604`

    .. plot::
        :width: 80%
        :include-source:

        from spectrum import window_visu
        window_visu(64, 'nuttall', mindB=-80)

    .. seealso:: :func:`create_window`, :class:`Window`


Instruction:
Here you have a function in Python 3, explain what it does
def window_tukey(N, r=0.5):
    assert r>=0 and r<=1 , "r must be in [0,1]"
    if N==1:
        return ones(1)

    if r == 0:
        return ones(N)
    elif r == 1:
        return window_hann(N)
    else:
        from numpy import flipud, concatenate, where

        ## cosine-tapered window
        x = linspace(0, 1, N)
        x1 = where(x<r/2.)
        w = 0.5*(1+cos(2*pi/r*(x[x1[0]]-r/2)))
        w = concatenate((w, ones(N-len(w)*2), flipud(w)))

        return w

Response:
Tukey tapering window (or cosine-tapered window)

    :param N: window length
    :param r: defines the ratio between the constant section and the cosine
      section. It has to be between 0 and 1.

    The function returns a Hanning window for `r=0` and a full box for `r=1`.

    .. plot::
        :width: 80%
        :include-source:

        from spectrum import window_visu
        window_visu(64, 'tukey')
        window_visu(64, 'tukey', r=1)

    .. math:: 0.5 (1+cos(2pi/r (x-r/2))) for 0<=x<r/2

    .. math:: 0.5 (1+cos(2pi/r (x-1+r/2))) for x>=1-r/2

    .. seealso:: :func:`create_window`, :class:`Window`


Instruction:
Can you generate a brief explanation for the following Python 3 code
def window_flattop(N, mode='symmetric',precision=None):
    assert mode in ['periodic', 'symmetric']
    t = arange(0, N)

    # FIXME: N=1 for mode = periodic ?
    if mode == 'periodic':
        x = 2*pi*t/float(N)
    else:
        if N ==1:
            return ones(1)
        x = 2*pi*t/float(N-1)
    a0 = 0.21557895
    a1 = 0.41663158
    a2 = 0.277263158
    a3 = 0.083578947
    a4 = 0.006947368

    if precision == 'octave':
        #to compare with octave, same as above but less precise
        d  = 4.6402
        a0 = 1./d
        a1 = 1.93/d
        a2 = 1.29/d
        a3 = 0.388/d
        a4 = 0.0322/d
    w = a0-a1*cos(x)+a2*cos(2*x)-a3*cos(3*x)+a4*cos(4*x)
    return w

Response: r Returns a flat - top window of the given length.


Instruction:
Explain what the following Python 3 code does
def window_taylor(N, nbar=4, sll=-30):
    B = 10**(-sll/20)
    A = log(B + sqrt(B**2 - 1))/pi
    s2 = nbar**2 / (A**2 + (nbar - 0.5)**2)
    ma = arange(1,nbar)
    def calc_Fm(m):
        numer = (-1)**(m+1) * prod(1-m**2/s2/(A**2 + (ma - 0.5)**2))
        denom = 2* prod([ 1-m**2/j**2 for j in ma if j != m])
        return numer/denom
    Fm = array([calc_Fm(m) for m in ma])
    def W(n):
        return 2 * np.sum(Fm * cos(2*pi*ma*(n-N/2 + 1/2)/N)) + 1
    w = array([W(n) for n in range(N)])
    # normalize (Note that this is not described in the original text)
    scale = W((N-1)/2)
    w /= scale
    return w

Response: Taper a window of size N with a given sll.


Instruction:
Can you generate the documentation for the following Python 3 function
def window_poisson(N, alpha=2):
    n = linspace(-N/2., (N)/2., N)
    w = exp(-alpha * abs(n)/(N/2.))
    return w

Response: r Poisson tapering window


Instruction:
Given the following Python 3 function, write the documentation
def window_poisson_hanning(N, alpha=2):
    w1 = window_hann(N)
    w2 = window_poisson(N, alpha=alpha)
    return w1*w2

Response: r Hann - Poisson tapering window


Instruction:
Create a Python 3 function to
compute the response for the frequency response of the current object.

Response:
def compute_response(self, **kargs):
        """Compute the window data frequency response

        :param norm: True by default. normalised the frequency data.
        :param int NFFT: total length of the final data sets( 2048 by default.
            if less than data length, then NFFT is set to the data length*2).

        The response is stored in :attr:`response`.

        .. note:: Units are dB (20 log10) since we plot the frequency response)

        """
        from numpy.fft import fft, fftshift

        norm = kargs.get('norm', self.norm)

        # do some padding. Default is max(2048, data.len*2)
        NFFT = kargs.get('NFFT', 2048)
        if NFFT < len(self.data):
            NFFT = self.data.size * 2

        # compute the fft modulus
        A = fft(self.data, NFFT)
        mag = abs(fftshift(A))

        # do we want to normalise the data
        if norm is True:
            mag = mag / max(mag)

        response = 20. * stools.log10(mag) # factor 20 we are looking at the response
                                    # not the powe
        #response = clip(response,mindB,100)
        self.__response = response


Instruction:
How would you code a function in Python 3 to
plot the frequency domain of the current object.

Response:
def plot_frequencies(self, mindB=None, maxdB=None, norm=True):
        """Plot the window in the frequency domain

        :param mindB: change the default lower y bound
        :param maxdB: change the default upper lower bound
        :param bool norm: if True, normalise the frequency response.

        .. plot::
            :width: 80%
            :include-source:

            from spectrum.window import Window
            w = Window(64, name='hamming')
            w.plot_frequencies()

        """
        from pylab import plot, title, xlim, grid, ylim, xlabel, ylabel
        # recompute the response
        self.compute_response(norm=norm)

        plot(self.frequencies, self.response)
        title("ENBW=%2.1f" % (self.enbw))
        ylabel('Frequency response (dB)')
        xlabel('Fraction of sampling frequency')
        # define the plot limits
        xlim(-0.5, 0.5)
        y0, y1 = ylim()
        if mindB:
            y0 = mindB
        if maxdB is not None:
            y1 = maxdB
        else:
            y1 = max(self.response)

        ylim(y0, y1)

        grid(True)


Instruction:
How would you explain what the following Python 3 function does
def plot_window(self):
        from pylab import plot, xlim, grid, title, ylabel, axis
        x = linspace(0, 1, self.N)
        xlim(0, 1)
        plot(x, self.data)
        grid(True)
        title('%s Window (%s points)' % (self.name.capitalize(), self.N))
        ylabel('Amplitude')
        axis([0, 1, 0, 1.1])

Response: Plot the window in the time domain


Instruction:
Write a Python 3 function that can
plot both time and frequency domain results.

Response:
def plot_time_freq(self, mindB=-100, maxdB=None, norm=True,
            yaxis_label_position="right"):
        """Plotting method to plot both time and frequency domain results.

        See :meth:`plot_frequencies` for the optional arguments.

        .. plot::
            :width: 80%
            :include-source:

            from spectrum.window import Window
            w = Window(64, name='hamming')
            w.plot_time_freq()

        """
        from pylab import subplot, gca

        subplot(1, 2, 1)
        self.plot_window()

        subplot(1, 2, 2)
        self.plot_frequencies(mindB=mindB, maxdB=maxdB, norm=norm)

        if yaxis_label_position=="left":
            try: tight_layout()
            except: pass
        else:
            ax = gca()
            ax.yaxis.set_label_position("right")


Instruction:
Create a Python 3 function for
solving the general toeplitz linear equations

Response:
def TOEPLITZ(T0, TC, TR, Z):
    """solve the general toeplitz linear equations

    Solve TX=Z

    :param T0: zero lag value
    :param TC: r1 to rN
    :param TR: r1 to rN

    returns X

    requires 3M^2+M operations instead of M^3 with gaussian elimination

    .. warning:: not used right now
    """
    assert len(TC)>0
    assert len(TC)==len(TR)
    M = len(TC)
    X = numpy.zeros(M+1,dtype=complex)
    A = numpy.zeros(M,dtype=complex)
    B = numpy.zeros(M,dtype=complex)
    P = T0
    if P == 0: raise ValueError("P must be different from zero")
    if P == 0: raise ValueError("P must be different from zero")
    X[0] = Z[0]/T0
    for k in range(0, M):
        save1 = TC[k]
        save2 = TR[k]
        beta = X[0]*TC[k]
        if k == 0:
            temp1 = -save1 / P
            temp2 = -save2 / P
        else:
            for j in range(0, k):
                save1 = save1 + A[j] * TC[k-j-1]
                save2 = save2 + B[j] * TR[k-j-1]
                beta = beta + X[j+1] * TC[k-j-1]
            temp1 = -save1 / P
            temp2 = -save2/P
        P = P * (1. - (temp1*temp2))
        if P <= 0:
            raise ValueError("singular matrix")
        A[k] = temp1
        B[k] = temp2
        alpha = (Z[k+1]-beta)/P
        if k == 0:
            X[k+1] = alpha
            for j in range(0,k+1):
                X[j] = X[j] + alpha * B[k-j]
            continue

        for j in range(0, k):
            kj = k-j-1
            save1 = A[j]
            A[j] = save1 + temp1 * B[kj]
            B[kj] = B[kj] + temp2*save1

        X[k+1] = alpha
        for j in range(0,k+1):
            X[j] = X[j] + alpha*B[k-j]
    return X


Instruction:
How would you explain what the following Python 3 function does
def get_short_module_name(module_name, obj_name):
    parts = module_name.split('.')
    short_name = module_name
    for i in range(len(parts) - 1, 0, -1):
        short_name = '.'.join(parts[:i])
        try:
            exec('from %s import %s' % (short_name, obj_name))
        except ImportError:
            # get the last working module name
            short_name = '.'.join(parts[:(i + 1)])
            break
    return short_name

Response: Get the shortest possible module name for a given object name.


Instruction:
Create a Python 3 function for
identifying and resolve used names in a codeobj.

Response:
def identify_names(code):
    """Builds a codeobj summary by identifying and resolving used names

    >>> code = '''
    ... from a.b import c
    ... import d as e
    ... print(c)
    ... e.HelloWorld().f.g
    ... '''
    >>> for name, o in sorted(identify_names(code).items()):
    ...     print(name, o['name'], o['module'], o['module_short'])
    c c a.b a.b
    e.HelloWorld HelloWorld d d
    """
    finder = NameFinder()
    finder.visit(ast.parse(code))

    example_code_obj = {}
    for name, full_name in finder.get_mapping():
        # name is as written in file (e.g. np.asarray)
        # full_name includes resolved import path (e.g. numpy.asarray)
        module, attribute = full_name.rsplit('.', 1)
        # get shortened module name
        module_short = get_short_module_name(module, attribute)
        cobj = {'name': attribute, 'module': module,
                'module_short': module_short}
        example_code_obj[name] = cobj
    return example_code_obj


Instruction:
Can you write a function in Python 3 where it
generates RST to place a thumbnail in a gallery

Response:
def _thumbnail_div(full_dir, fname, snippet, is_backref=False):
    """Generates RST to place a thumbnail in a gallery"""
    thumb = os.path.join(full_dir, 'images', 'thumb',
                         'sphx_glr_%s_thumb.png' % fname[:-3])
    ref_name = os.path.join(full_dir, fname).replace(os.path.sep, '_')

    template = BACKREF_THUMBNAIL_TEMPLATE if is_backref else THUMBNAIL_TEMPLATE
    return template.format(snippet=snippet, thumbnail=thumb, ref_name=ref_name)


Instruction:
Can you generate a brief explanation for the following Python 3 code
def modcovar_marple (X,IP):
    Pv = []
    N = len(X)
    A = np.zeros(N, dtype=complex)
    D = np.zeros(N, dtype=complex)
    C = np.zeros(N, dtype=complex)
    R = np.zeros(N, dtype=complex)
    #   Initialization
    R1=0.
    for K in range(1, N-1):
        R1=R1 + 2.*(X[K].real**2 + X[K].imag**2)
    R2 = X[0].real**2 + X[0].imag**2
    R3 = X[N-1].real**2 + X[N-1].imag**2
    R4 = 1. / (R1 + 2. * (R2 + R3))
    P = R1 + R2 + R3
    DELTA = 1. - R2 * R4
    GAMMA = 1. - R3 * R4
    LAMBDA = (X[0] * X[N-1]).conjugate()*R4
    C[0] = X[N-1] * R4
    D[0] = X[0].conjugate() * R4

    M = 0
    if (IP ==0):
        P = (.5*R1+R2+R3)/float(N)
        return [], P, []

    #C   Main loop

    for M in range(0, IP):
        #print '---------------------', M
        SAVE1 = 0+0j
        for K in range(M+1, N):
            SAVE1 = SAVE1 + X[K]*X[K-M-1].conjugate()
        SAVE1 *= 2.
        R[M] = SAVE1.conjugate()
        THETA = X[N-1]*D[0]
        PSI=X[N-1]*C[0]
        XI = X[0].conjugate() * D[0]
        if M==0:
            pass
        else:
            for K in range(0, M):
                THETA=THETA+X[N-K-2]*D[K+1]    # Eq. (8.D.45)
                PSI = PSI + X[N-K-2]*C[K+1]    # Eq. (8.D.45)
                XI = XI + X[K+1].conjugate() * D[K+1] # Eq. (8.D.45)
                R[K] = R[K]-X[N-M-1] * X[N+1-M+K-1].conjugate() - X[M].conjugate() * X[M-K-1] # Eq. (8.D.37)
                SAVE1=SAVE1+R[K].conjugate()*A[M-K-1]             # Eq. (8.D.24)
                #print 'withini loop', K, THETA, PSI, XI, R[K], SAVE1
                #print 'x   -------', C[K], C[K+1]
                #print 'x   -------', D[K], D[K+1]
                #print 'x   -------', N-K-2, K+1,N-M-1,  M, M-K-1
                #print 'x   -------', X[N-K-2], X[K+1],X[N-M-1],  X[M], X[M-K-1]

        #  Order update of A vector

        C1 = -SAVE1/P
        A[M]=C1                                   # Eq. (8.D.23)
        P=P*(1.-C1.real**2-C1.imag**2)            # Eq. (8.D.25)
        #print 'C1=' , C1, 'A[M]', A[M], 'P=',P
        if M==0:
            pass
        else:
            #for k in range(0, (M-1)/2+1):
            #print 'BEFORE', A[0:4]
            for K in range(0, (M+1)//2):
                MK = M-K-1
                SAVE1=A[K]
                A[K]=SAVE1+C1*A[MK].conjugate() # Eq. (8.D.22)
                #print 'A uopdate---->',M, K, MK, A[K], A[MK], SAVE1, C1
                if (K != MK):
                    #print 'ENTERI IF', K, MK, A[MK], C1, SAVE1
                    A[MK]=A[MK]+C1*(SAVE1.conjugate()) # Eq. (8.D.22)
            #print 'AFTER', A[0:4]
        #print M+1, IP
        if M+1 == IP:
            #Pv.append(P)
            P=.5*P/float(N-M-1)
            Pv.append(P)
            return A, P, Pv
        else:
            Pv.append(.5*P/float(N-M-1))
            #Pv.append(P)

        #   Time update of C,D vectors and GAMMA,DELTA,LAMBDA scalars

        R1=1./(DELTA*GAMMA-(LAMBDA.real)**2-(LAMBDA.imag)**2)
        C1=(THETA*(LAMBDA.conjugate())+PSI*DELTA)*R1
        C2=(PSI*LAMBDA+THETA*GAMMA)*R1
        C3=(XI*(LAMBDA.conjugate())+THETA*DELTA)*R1
        C4=(THETA*LAMBDA+XI*GAMMA)*R1

        #print 'C1C2C3C4', C1, C2, C3, C4
        #print M, M/2+1, (M-1)/2+1
        for K in range(0, (M)//2+1):
            MK=M-K
            SAVE1=C[K].conjugate()
            SAVE2=D[K].conjugate()
            SAVE3=C[MK].conjugate()
            SAVE4=D[MK].conjugate()
            C[K]=C[K]+C1*SAVE3+C2*SAVE4                # Eq. (8.D.43)
            D[K]=D[K]+C3*SAVE3+C4*SAVE4                # Eq. (8.D.44)
            #print '-------->', K,MK, SAVE1, SAVE2, SAVE3, SAVE4
            if K != MK:
                C[MK]=C[MK]+C1*SAVE1+C2*SAVE2              # Eq. (8.D.43)
                D[MK]=D[MK]+C3*SAVE1+C4*SAVE2              # Eq. (8.D.44)
                #print 'witninloop loop ',K,MK,C[MK], D[MK]
        #print 'after loop'
        #print 'C=',C[0:2]
        #print 'D=',D[0:2]
        R2=PSI.real**2+PSI.imag**2
        R3=THETA.real**2+THETA.imag**2
        R4=XI.real**2+XI.imag**2
        R5=GAMMA-(R2*DELTA+R3*GAMMA+2.*np.real(PSI*LAMBDA*THETA.conjugate()))*R1
        R2=DELTA-(R3*DELTA+R4*GAMMA+2.*np.real(THETA*LAMBDA*XI.conjugate()))*R1
        GAMMA=R5                                     # Eq. (8.D.46)
        DELTA=R2                                     # Eq. (8.D.47)
        LAMBDA=LAMBDA+C3*PSI.conjugate()+C4*THETA.conjugate()  # Eq. (8.D.48)
        #print 'before time updaqt',R2, R3, R4, R5, LAMBDA
        if P <= 0.:
            raise ValueError('Found an invalid negative value for P.')
        if (DELTA > 0. and DELTA <= 1. and GAMMA > 0. and GAMMA <=1.):
            pass
        else:
            raise ValueError('Found an invalid DELTA or GAMMA value.')
        #   Time update of A vector; order updates of C,D vectors aand GAMMA,
        #   DELTA,LAMBDA scalars
        #print 'time update--------------'
        R1=1./P
        R2=1./(DELTA*GAMMA-LAMBDA.real**2-LAMBDA.imag**2) # Eq. (8.D.41)
        EF=X[M+1]
        EB=X[N-M-2]
        #print 'efeb', EF, EB
        #print 'A=',A[0:2]
        for K in range(0, M+1):
            #print 'efeb lloop', K,A[K], X[M-K], X[N-M+K-1]
            EF=EF+A[K]*X[M-K]                        # Eq. (8.D.1)
            EB=EB+A[K].conjugate()*X[N-M+K-1]            # Eq. (8.D.2)
        C1=EB*R1                                     # Eq. (8.D.28)
        C2=EF.conjugate()*R1                              # Eq. (8.D.29)
        C3=(EB.conjugate()*DELTA+EF*LAMBDA)*R2
        C4=(EF*GAMMA+(EB*LAMBDA).conjugate())*R2

        #print 'c1c2c3c4', C1 ,C2, C3, C4
        #print 'efeb',EF, EB

        for K in range(M, -1, -1):
            SAVE1=A[K]
            A[K]=SAVE1+C3*C[K]+C4*D[K]                 # Eq. (8.D.38)
            C[K+1]=C[K]+C1*SAVE1                       # Eq. (8.D.26)
            D[K+1]=D[K]+C2*SAVE1                       # Eq. (8.D.27)
            #print 'ACD',K, A[K], C[K+1], D[K+1]
        C[0]=C1
        D[0]=C2
        R3=EB.real**2+EB.imag**2
        R4=EF.real**2+EF.imag**2
        P=P-(R3*DELTA+R4*GAMMA+2.*np.real(EF*EB*LAMBDA))*R2  # Eq. (8.D.42)
        DELTA=DELTA-R4*R1                            # Eq. (8.D.32)
        GAMMA=GAMMA-R3*R1                            # Eq. (8.D.33)
        LAMBDA=LAMBDA+(EF*EB).conjugate()*R1                # Eq. (8.D.35)

        #print 'final'
        #print R3, R4, P, DELTA, GAMMA, LAMBDA
        #print 'Afinal=',A[0:2]
        #print 'P=',P
        if (P > 0.):
            pass
        else:
            raise ValueError("Found a invalid negative P value ")
        if (DELTA > 0. and DELTA <= 1. and  GAMMA > 0. and GAMMA <= 1.):
            pass
        else:
            raise ValueError("Found an invalid negative GAMMA or DELTA value ")

Response: Fast algorithm for the modified covariance least squares normal equations.


Instruction:
Here you have a function in Python 3, explain what it does
def modcovar(x, order):
    from spectrum import corrmtx
    import scipy.linalg
    X = corrmtx(x, order, 'modified')
    Xc = np.matrix(X[:,1:])
    X1 = np.array(X[:,0])

    # Coefficients estimated via the covariance method
    # Here we use lstsq rathre than solve function because Xc is not square matrix
    a, residues, rank, singular_values = scipy.linalg.lstsq(-Xc, X1)

    # Estimate the input white noise variance

    Cz = np.dot(X1.conj().transpose(), Xc)
    e = np.dot(X1.conj().transpose(), X1) + np.dot(Cz, a)
    assert e.imag < 1e-4, 'wierd behaviour'
    e = float(e.real) # ignore imag part that should be small

    return a, e

Response: Simple and fast implementation of the covariance AR estimate of the real and imaginary noise of the given complex data samples.


Instruction:
Explain what the following Python 3 code does
def aryule(X, order, norm='biased', allow_singularity=True):
    assert norm in ['biased', 'unbiased']
    r = CORRELATION(X, maxlags=order, norm=norm)
    A, P, k = LEVINSON(r, allow_singularity=allow_singularity)
    return A, P, k

Response: r Returns the polynomial A corresponding to the set of complex data values X to X.


Instruction:
Implement a Python 3 function for
computing the autocorrelation coefficients R based on the prediction polynomial A and the final prediction error Efinal.

Response:
def rlevinson(a, efinal):
    """computes the autocorrelation coefficients, R based
    on the prediction polynomial A and the final prediction error Efinal,
    using the stepdown algorithm.

    Works for real or complex data

    :param a:
    :param efinal:

    :return:
        * R, the autocorrelation
        * U  prediction coefficient
        * kr reflection coefficients
        * e errors

    A should be a minimum phase polynomial and A(1) is assumed to be unity.

    :returns: (P+1) by (P+1) upper triangular matrix, U,
        that holds the i'th order prediction polynomials
        Ai, i=1:P, where P is the order of the input
        polynomial, A.

             [ 1  a1(1)*  a2(2)* ..... aP(P)  * ]
             [ 0  1       a2(1)* ..... aP(P-1)* ]
       U  =  [ .................................]
             [ 0  0       0      ..... 1        ]

    from which the i'th order prediction polynomial can be extracted
    using Ai=U(i+1:-1:1,i+1)'. The first row of U contains the
    conjugates of the reflection coefficients, and the K's may be
    extracted using, K=conj(U(1,2:end)).

    .. todo:: remove the conjugate when data is real data, clean up the code
       test and doc.

    """
    a = numpy.array(a)
    realdata = numpy.isrealobj(a)

    assert a[0] == 1, 'First coefficient of the prediction polynomial must be unity'

    p = len(a)

    if p < 2:
        raise ValueError('Polynomial should have at least two coefficients')

    if realdata == True:
        U = numpy.zeros((p, p)) # This matrix will have the prediction
                                # polynomials of orders 1:p
    else:
        U = numpy.zeros((p, p), dtype=complex)
    U[:, p-1] = numpy.conj(a[-1::-1]) # Prediction coefficients of order p

    p = p -1
    e = numpy.zeros(p)

    # First we find the prediction coefficients of smaller orders and form the
    # Matrix U

    # Initialize the step down

    e[-1] = efinal # Prediction error of order p

    # Step down
    for k in range(p-1, 0, -1):
        [a, e[k-1]] = levdown(a, e[k])
        U[:, k] = numpy.concatenate((numpy.conj(a[-1::-1].transpose()) ,
                                      [0]*(p-k) ))

    e0 = e[0]/(1.-abs(a[1]**2)) #% Because a[1]=1 (true polynomial)
    U[0,0] = 1                #% Prediction coefficient of zeroth order
    kr = numpy.conj(U[0,1:])     #% The reflection coefficients
    kr = kr.transpose()                 #% To make it into a column vector

    #   % Once we have the matrix U and the prediction error at various orders, we can
    #  % use this information to find the autocorrelation coefficients.

    R = numpy.zeros(1, dtype=complex)
    #% Initialize recursion
    k = 1
    R0 = e0 # To take care of the zero indexing problem
    R[0] = -numpy.conj(U[0,1])*R0   # R[1]=-a1[1]*R[0]

    # Actual recursion
    for k in range(1,p):
        r = -sum(numpy.conj(U[k-1::-1,k])*R[-1::-1]) - kr[k]*e[k-1]
        R = numpy.insert(R, len(R), r)

    # Include R(0) and make it a column vector. Note the dot transpose

    #R = [R0 R].';
    R = numpy.insert(R, 0, e0)
    return R, U, kr, e


Instruction:
Can you tell what is the following Python 3 function doing
def levup(acur, knxt, ecur=None):
    if acur[0] != 1:
        raise ValueError('At least one of the reflection coefficients is equal to one.')
    acur = acur[1:] #  Drop the leading 1, it is not needed

    # Matrix formulation from Stoica is used to avoid looping
    anxt = numpy.concatenate((acur, [0])) + knxt * numpy.concatenate((numpy.conj(acur[-1::-1]), [1]))

    enxt = None
    if ecur is not None:
        # matlab version enxt = (1-knxt'.*knxt)*ecur
        enxt = (1. - numpy.dot(numpy.conj(knxt), knxt)) * ecur

    anxt = numpy.insert(anxt, 0, 1)

    return anxt, enxt

Response: One step forward Levinson recursion


Instruction:
Can you generate the documentation for the following Python 3 function
def arcovar_marple(x, order):
    assert len(x) >= order, "X must be dimensioned >=N"

    #   ----------------------------------------------------- Initialization
    x = np.array(x)
    N = len(x)

    # Equations 8.C.42
    r0 = sum(abs(x)**2.)
    r1 = abs(x[0])**2
    rN = abs(x[N-1])**2

    pf = r0 - r1
    pb = r0 - rN

    delta = 1. - r1 / r0
    gamma = 1. - rN / r0

    c = np.zeros(N, dtype=complex)
    d = np.zeros(N, dtype=complex)
    r = np.zeros(N, dtype=complex)
    af = np.zeros(N, dtype=complex)
    ab = np.zeros(N, dtype=complex)

    c[0] = x[N-1].conjugate() / r0
    d[0] = x[0].conjugate() / r0

    # special case
    if order == 0:
        pf = r0 / float(N)
        pb = pf
        return af, pf, ab, pb, 0

    # ----------------------------------------------------------  MAIN LOOP

    #ip +1 because we want to enter in the loop to run the first part of the code.
    pbv = []
    for m in range(0, order+1):
        logging.debug('----------------------------m=', m)
        logging.debug(c[0:2])
        logging.debug(d[0:2])
        r1 = 1./pf
        r2 = 1./pb
        r3 = 1./delta
        r4 = 1./gamma

        #logging.debug('starting r1r2r3r4=', r1, r2, r3, r4, pf, pb, delta, gamma)

        #Order update: AF and AB vectors ; time update: C and D vectors
        temp = 0.+0.j
        for k in range(m+1, N):
            temp = temp + x[k]*x[k-m-1].conjugate()

        r[m] =  temp.conjugate()
        theta = x[0] * c[m]
        #print(('theta', theta))
        #    print(('c=', c[0:2]))
        #    print(('d=', d[0:2]))
        if m == 0:
            pass
        else:
            for k in range(0, m):
                theta = theta + x[m-k] * c[k]                   # Eq. (8.C.39)
                r[k] = r[k] - x[N-m-1] * x[N-m+k].conjugate() # Eq. (8.C.32)
                temp = temp + af[m-k-1] * r[k].conjugate()
                #print 'loop1 k=', k
                #print '         theta=',theta, 'r[k]=',r[k], 'temp=', temp
                #print '         c=',c[k], 'af=',af[m-k-1]
        """if m > 0:
            if debug:
                print((m, N-m))
                print(('Xk=0',x[m-0],x[N-m-1], x[N-m+0]))
            if m > 1:
                if debug:
                    print('Xk=1',x[m-1],x[N-m-1], x[N-m+1])
        """
        c1 = -temp * r2
        c2 = -r1 * temp.conjugate()
        c3 = theta * r3
        c4 = r4 *theta.conjugate()
        #if debug:
        #    print('c1 c2 c3 c4 before af=',c1 ,c2 ,c3 ,c4)
        af[m] = c1                    #             ! Eq. (8.C.19)
        ab[m] = c2                    #             ! Eq. (8.C.22)
        save = c[m]
        c[m] = save + c3*d[m]
        d[m] = d[m] + c4*save
        #if debug:
        #    print('res',m,'af[m]=',af[m], ab[m], save, 'temp=',temp)

        if m == 0:
            pass
        else:
            #if debug:print('af before', af[0:2])
            for k in range(0, m):
                save = af[k]
                af[k] = save + c1 * ab[m-k-1] # Eq. (8.C.18)
                ab[m-k-1] = ab[m-k-1] + c2 * save   # Eq. (8.C.21)

                save = c[k]
                c[k] = save + c3*d[k]       # Eq. (8.C.37)
                d[k] = d[k] + c4*save       # Eq. (8.C.38)
                #if debug:
                #    print('loop2 k=', k)
                #    print('      af[k]=', af[k])
                #    print('      ab[m-k-1]=', ab[m-k-1])
                #    print('      c[k]=', c[k])
                #    print('      d[k]=', d[k])
            #if debug:
            #    print('af after=', af[0:2])
            #    print('ab=', ab[0:2])

        r5 = temp.real**2 + temp.imag**2
        pf = pf - r5*r2         # Eq. (8.C.20)
        pb = pb - r5*r1         # Eq. (8.C.23)
        r5 = theta.real**2 + theta.imag**2
        delta = delta - r5*r4               # Eq. (8.C.39)
        gamma = gamma - r5*r3               # Eq. (8.C.40)
        #if debug:
        #    print('r5r2r1deltagamma', r5, r2, r1 , delta, gamma)
        #    print('pf before norm', pf, pb, N-m-1)
        if m != order-1:
            pass
        else:
            pf = pf / float(N-m-1)
            pb = pb / float(N-m-1)
            #if debug:
            #    print('ENDING', N-m-1)
            break

        #if debug:
        #    print('pf and pb', pf, pb)
        if pf > 0 and pb > 0:
            pass
        else:
            ValueError("Negative PF or PB value")
        if (delta > 0. and delta <=1 and gamma > 0. and gamma <=1):
            pass
        else:
            ValueError("Invalid delta or gamma value")

        #C   Time update:  AF and AB vectors; order update:  C and D vectors

        r1 = 1./pf
        r2 = 1./pb
        r3 = 1./delta
        r4 = 1./gamma
        #if debug:
        #    print('--------time update', r1, r2, r3, r4, m+1, N-m-1, x[m+1], x[N-m-2])
        ef = x[m+1]
        eb = x[(N-1)-m-1]

        for k in range(0,m+1):
            #print 'k=', k, 'ef=', ef, ' eb=',eb,' af=',af[k], ab[k]
            #print x[m-k],x[N-m+k-1]
            ef = ef + af[k] * x[m-k]             # Eq. (8.C.1)
            eb = eb + ab[k] * x[N-m+k-1]                   # Eq. (8.C.2)

        #ef = sum(af)

        #if debug:
        #    print('efweb', ef , eb)
        c1 = ef*r3
        c2 = eb*r4
        c3 = eb.conjugate() * r2
        c4 = ef.conjugate() * r1
        #if debug:
        #    print('c1c2c3c4', c1, c2, c3, c4)
        #    print('af before', af[0:2])
        for k in range(m, -1, -1):
            save = af[k]
            af[k] = save + c1 * d[k]                    #  Eq. (8.C.33)
            d[k+1] = d[k] + c4 * save                    # Eq. (8.C.25)
            save = ab[k]
            ab[k] = save + c2 * c[m-k]                 # Eq. (8.C.35)
            c[m-k] = c[m-k] + c3 * save              # Eq. (8.C.24)
        #if debug:
        #    print('af after', af[0:2])
        #    print('d', d[0:2])
        #    print('ab', ab[0:2])
        #    print('c', c[0:2])
        #if debug:print('Pb before', pf, pb)
        c[m+1] = c3
        d[0] = c4
        #r5 = abs(ef)**2
        r5 = ef.real**2 + ef.imag**2
        pf = pf - r5 * r3                              # Eq. (8.C.34)

        delta = delta-r5 * r1                        # Eq. (8.C.30)
        #r5 = abs(eb)**2
        r5 = eb.real**2 + eb.imag**2
        pb = pb - r5 * r4                              # Eq. (8.C.36)
        #if debug:
        #    print('Pb---------------------', m, pb, r5, r4)
        gamma = gamma-r5*r2                        # Eq. (8.C.31)
        pbv.append(pb)

        if (pf > 0. and pb > 0.):
            pass
        else:
            ValueError("Negative PF or PB value")
        #if debug:
        #    print(delta, gamma)
        if (delta > 0. and delta <= 1.) and (gamma > 0. and gamma <= 1.):
            pass
        else:
            ValueError("Invalid delta or gamma value")

    #af=array of forward coeff
    #ab=array of barward coeff
    #pb=backward variance
    #pf=forward variance
    return af, pf, ab, pb, pbv

Response: r Estimates AR model parameters using covariance method Marple.


Instruction:
Can you tell what is the following Python 3 function doing
def arcovar(x, order):

    from spectrum import corrmtx
    import scipy.linalg

    X = corrmtx(x, order, 'covariance')
    Xc = np.matrix(X[:, 1:])
    X1 = np.array(X[:, 0])

    # Coefficients estimated via the covariance method
    # Here we use lstsq rathre than solve function because Xc is not square
    # matrix

    a, _residues, _rank, _singular_values = scipy.linalg.lstsq(-Xc, X1)

    # Estimate the input white noise variance
    Cz = np.dot(X1.conj().transpose(), Xc)
    e = np.dot(X1.conj().transpose(), X1) + np.dot(Cz, a)
    assert e.imag < 1e-4, 'wierd behaviour'
    e = float(e.real) # ignore imag part that should be small

    return a, e

Response: r Simple and fast implementation of the covariance AR estimate