<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def bird(X, scales, n_runs, p_above, max_iter=100, random_state=None, n_jobs=1, memory=Memory(None), verbose=False):
 """ The BIRD algorithm as described in the paper Parameters X : array, shape (n_channels, n_times) The numpy n_channels-vy-N array to be X_denoised where n_channels is number of sensors and n_times the dimension scales : list The list of MDCT scales that will be used to built the dictionary Phi n_runs : int the number of runs (n_runs in the paper) p_above : float probability of appearance of the max above which the noise hypothesis is considered false max_iter : int The maximum number of iterations in one pursuit. random_state : None | int | np.random.RandomState To specify the random generator state (seed). max_iter : int The maximum number of iterations in one pursuit. n_jobs : int The number of jobs to run in parallel. memory : instance of Memory The object to use to cache some computations. If cachedir is None, no caching is performed. verbose : bool verbose mode Returns ------- X_denoise : array, shape (n_channels, n_times) The X_denoised data. """

    X, prepad = _pad(X)

    # Computing Lambda_W(Phi, p_above)
    N = float(X.shape[1])
    # size of the full shift-invariant dictionary
    M = np.sum(np.array(scales) / 2) * N
    sigma = sqrt((1.0 - (2.0 / np.pi)) / float(N))
    Lambda_W = sigma * sqrt(2.0) * erfinv((1.0 - p_above) ** (1.0 / float(M)))
    print("Starting BIRD with MDCT dictionary of %d Atoms. "
          "Lambda_W=%1.3f, n_runs=%d" % (M, Lambda_W, n_runs))
    X_denoised = _bird_core(X, scales, n_runs, Lambda_W, verbose=verbose,
                            max_iter=max_iter, indep=True, n_jobs=n_jobs,
                            random_state=random_state, memory=memory)
    return X_denoised[:, prepad:]