Example #1
0
def harmonic_ilc_alm(components, instrument, alms, lbins=None, fsky=None):
    """ Internal Linear Combination of alms

    Parameters
    ----------
    components: list or tuple of lists
        `Components` of the mixing matrix. They must have no free parameter.
    instrument:
        Object that provides the following as a key or an attribute.

        - **frequency**

        It can be anything that is convertible to a float numpy array.
    alms: ndarray
        Data vector to be separated. Shape ``(n_freq, ..., lm)``.
        ``...`` can be 1, 3 or absent. The ILC weights are computed
	independently for each of its indices.
    lbins: array
        It stores the edges of the bins that will have the same ILC weights.
	If a multipole is not in a bin but is the alms, an independent bin
	will be assigned to it
    fsky: array
        If provided the output power spectra are corrected for this factor

    Returns
    -------
    result : dict
	It includes

        - **W**: *(ndarray)* - ILC weights for each component and possibly
	  each index of the `...` dimension in the alms.
        - **s**: *(ndarray)* - Alms of the cleaned components
        - **cl_in**: *(ndarray)* - Spectra of the input alm
        - **cl_out**: *(ndarray)* - Spectra of the output alm
        - **fsky**: *(ndarray)* - The input fsky used to correct the cls

    """
    cl_in = np.array([hp.alm2cl(alm) for alm in alms])

    mm = MixingMatrix(*components)
    A = mm.eval(instrument.frequency)

    cov = _empirical_harmonic_covariance(alms)
    if lbins is not None:
        for lmin, lmax in zip(lbins[:-1], lbins[1:]):
            # Average the covariances in the bin
            lmax = min(lmax, cov.shape[-1])
            dof = 2 * np.arange(lmin, lmax) + 1
            cov[..., lmin:lmax] = ((dof / dof.sum() *
                                    cov[..., lmin:lmax]).sum(-1))[...,
                                                                  np.newaxis]
    cov = _regularized_inverse(cov.swapaxes(-1, -3))
    ilc_filter = np.linalg.inv(A.T @ cov @ A) @ A.T @ cov
    del cov, dof

    res = OptimizeResult()
    res.s = _apply_harmonic_W(ilc_filter, alms)

    # Craft output
    cl_out = np.array([hp.alm2cl(alm) for alm in res.s])
    res.cl_in = cl_in
    res.cl_out = cl_out
    if fsky:
        res.cl_in /= fsky
        res.cl_out /= fsky

    res.fsky = fsky
    res.W = ilc_filter

    return res