コード例 #1
0
def rmmd(input, mask, sig):
    """
    removes the dipole and mask of input file
    if mask = "auto" uses 30 deg sky cut
    """
    import healpy as hp
    try:
        m = hp.read_map(
            input,
            field=(0, 1, 2),
            verbose=False,
            dtype=None,
        )
    except:
        m = hp.read_map(
            input,
            field=(0, ),
            verbose=False,
            dtype=None,
        )
    nside = hp.get_nside(m)
    npix = hp.nside2npix(nside)
    print(f"Nside: {nside}, npix: {npix}")
    # Mask map for dipole estimation

    m_masked = hp.ma(m)
    if mask:
        m_masked.mask = np.logical_not(
            hp.read_map(
                mask,
                verbose=False,
                dtype=None,
            ))

    # Fit dipole to masked map
    for i in sig:
        if not mask:
            mono, dip = hp.fit_dipole(m_masked[i], gal_cut=30)
        else:
            mono, dip = hp.fit_dipole(m_masked[i])

        # Subtract dipole map from data
        click.echo(click.style("Removing dipole:", fg="yellow"))
        click.echo(click.style("Dipole vector:", fg="green") + f" {dip}")
        click.echo(
            click.style("Dipole amplitude:", fg="green") +
            f" {np.sqrt(np.sum(dip ** 2))}")
        click.echo(click.style("Monopole:", fg="green") + f" {mono}")
        # Create dipole template
        ray = range(npix)
        vecs = hp.pix2vec(nside, ray)
        dipole = np.dot(dip, vecs)
        m[i] = m[i] - dipole - mono
    hp.write_map(input.replace(".fits", "_no-md.fits"),
                 m,
                 dtype=None,
                 overwrite=True)
コード例 #2
0
def get_dipole_dir(sky):
    '''
    Return the direction of the reconstructed dipole
        in (RA, dec) coordinated
    '''
    mono, dipole = hp.fit_dipole(sky)
    d = hp.vec2ang(dipole, lonlat=True)
    return (d[0][0], d[1][0])
コード例 #3
0
def remove_md(m, remove_dipole, remove_monopole, nside):
    if remove_monopole:
        dip_mask_name = remove_monopole
    if remove_dipole:
        dip_mask_name = remove_dipole
    # Mask map for dipole estimation
    if dip_mask_name == 'auto':
        mono, dip = hp.fit_dipole(m, gal_cut=30)
    else:
        m_masked = hp.ma(m)
        m_masked.mask = np.logical_not(
            hp.read_map(
                dip_mask_name,
                verbose=False,
                dtype=None,
            ))

        # Fit dipole to masked map
        mono, dip = hp.fit_dipole(m_masked)

    # Subtract dipole map from data
    if remove_dipole:
        click.echo(click.style("Removing dipole:", fg="yellow"))
        click.echo(click.style("Dipole vector:", fg="green") + f" {dip}")
        click.echo(
            click.style("Dipole amplitude:", fg="green") +
            f" {np.sqrt(np.sum(dip ** 2))}")

        # Create dipole template
        nside = int(nside)
        ray = range(hp.nside2npix(nside))
        vecs = hp.pix2vec(nside, ray)
        dipole = np.dot(dip, vecs)

        m = m - dipole
    if remove_monopole:
        click.echo(click.style("Removing monopole:", fg="yellow"))
        click.echo(click.style("Mono:", fg="green") + f" {mono}")
        m = m - mono
    return m
コード例 #4
0
def get_dipole_ampl(sky, subtract_noise=False, iso_map=None):
    '''
    Returns the reconstructed dipole amplitude
    If subtract_noise is True, use the procedure,
        described in Fermi paper (1903.02905)
        for the noise subtraction.
        Exposure map should be provided in this case
    '''
    if not subtract_noise:
        mono, dipole = hp.fit_dipole(sky)
        return np.sqrt((dipole * dipole).sum())
    else:
        if iso_map is None:
            raise ValueError("Please, specify the isotropy map")
        C_ell = hp.anafast(sky)[1]
        obs_map = get_obs_map(iso_map, sky)
        C_N = 4. * np.pi / len(iso_map)**2 * (obs_map / iso_map**2).sum()
        # C_N /= 1.35**2
        return 3 * np.sqrt((C_ell - C_N) / 4 / np.pi)
コード例 #5
0
ファイル: test_dipole.py プロジェクト: paganol/litebird_sim
def test_solar_dipole_fit(tmpdir):
    tmpdir = Path(tmpdir)

    test = unittest.TestCase()

    # The purpose of this test is to simulate the motion of the spacecraft
    # for one year (see `time_span_s`) and produce *two* timelines: the first
    # is associated with variables `*_s_o` and refers to the case of a nonzero
    # velocity of the Solar System, and the second is associated with variables
    # `*_o` and assumes that the reference frame of the Solar System is the
    # same as the CMB's (so that there is no dipole).

    start_time = Time("2022-01-01")
    time_span_s = 365 * 24 * 3600
    nside = 256
    sampling_hz = 1

    sim = lbs.Simulation(start_time=start_time, duration_s=time_span_s)

    scanning = lbs.SpinningScanningStrategy(
        spin_sun_angle_rad=0.785_398_163_397_448_3,
        precession_rate_hz=8.664_850_513_998_931e-05,
        spin_rate_hz=0.000_833_333_333_333_333_4,
        start_time=start_time,
    )

    spin2ecliptic_quats = scanning.generate_spin2ecl_quaternions(
        start_time, time_span_s, delta_time_s=7200
    )

    instr = lbs.InstrumentInfo(
        boresight_rotangle_rad=0.0,
        spin_boresight_angle_rad=0.872_664_625_997_164_8,
        spin_rotangle_rad=3.141_592_653_589_793,
    )

    det = lbs.DetectorInfo(
        name="Boresight_detector",
        sampling_rate_hz=sampling_hz,
        bandcenter_ghz=100.0,
        quat=[0.0, 0.0, 0.0, 1.0],
    )

    (obs_s_o,) = sim.create_observations(detectors=[det])
    (obs_o,) = sim.create_observations(detectors=[det])

    pointings = lbs.scanning.get_pointings(
        obs_s_o,
        spin2ecliptic_quats=spin2ecliptic_quats,
        detector_quats=[det.quat],
        bore2spin_quat=instr.bore2spin_quat,
    )

    orbit_s_o = lbs.SpacecraftOrbit(obs_s_o.start_time)
    orbit_o = lbs.SpacecraftOrbit(obs_o.start_time, solar_velocity_km_s=0.0)

    assert orbit_s_o.solar_velocity_km_s == 369.8160
    assert orbit_o.solar_velocity_km_s == 0.0

    pos_vel_s_o = lbs.spacecraft_pos_and_vel(orbit_s_o, obs_s_o, delta_time_s=86400.0)
    pos_vel_o = lbs.spacecraft_pos_and_vel(orbit_o, obs_o, delta_time_s=86400.0)

    assert pos_vel_s_o.velocities_km_s.shape == (366, 3)
    assert pos_vel_o.velocities_km_s.shape == (366, 3)

    lbs.add_dipole_to_observations(
        obs_s_o, pointings, pos_vel_s_o, dipole_type=lbs.DipoleType.LINEAR
    )
    lbs.add_dipole_to_observations(
        obs_o, pointings, pos_vel_o, dipole_type=lbs.DipoleType.LINEAR
    )

    npix = hp.nside2npix(nside)
    pix_indexes = hp.ang2pix(nside, pointings[0, :, 0], pointings[0, :, 1])

    h = np.zeros(npix)
    m = np.zeros(npix)
    map_s_o = np.zeros(npix)
    map_o = np.zeros(npix)

    bin_map(
        tod=obs_s_o.tod,
        pixel_indexes=pix_indexes,
        binned_map=map_s_o,
        accum_map=m,
        hit_map=h,
    )
    import healpy

    healpy.write_map(tmpdir / "map_s_o.fits.gz", map_s_o, overwrite=True)

    bin_map(
        tod=obs_o.tod,
        pixel_indexes=pix_indexes,
        binned_map=map_o,
        accum_map=m,
        hit_map=h,
    )

    healpy.write_map(tmpdir / "map_o.fits.gz", map_o, overwrite=True)

    dip_map = map_s_o - map_o

    assert np.abs(np.nanmean(map_s_o) * 1e6) < 1
    assert np.abs(np.nanmean(map_o) * 1e6) < 1
    assert np.abs(np.nanmean(dip_map) * 1e6) < 1

    dip_map[np.isnan(dip_map)] = healpy.UNSEEN
    mono, dip = hp.fit_dipole(dip_map)

    r = hp.Rotator(coord=["E", "G"])
    l, b = hp.vec2ang(r(dip), lonlat=True)

    # Amplitude, longitude and latitude
    test.assertAlmostEqual(np.sqrt(np.sum(dip ** 2)) * 1e6, 3362.08, 1)
    test.assertAlmostEqual(l[0], 264.021, 1)
    test.assertAlmostEqual(b[0], 48.253, 1)
コード例 #6
0
def Plotter(
    input,
    dataset,
    nside,
    auto,
    min,
    max,
    mid,
    rng,
    colorbar,
    lmax,
    fwhm,
    mask,
    mfill,
    sig,
    remove_dipole,
    logscale,
    size,
    white_background,
    darkmode,
    png,
    cmap,
    title,
    ltitle,
    unit,
    scale,
    outdir,
    verbose,
    data,
):
    rcParams["backend"] = "agg" if png else "pdf"
    rcParams["legend.fancybox"] = True
    rcParams["lines.linewidth"] = 2
    rcParams["savefig.dpi"] = 300
    rcParams["axes.linewidth"] = 1

    masked = False

    if darkmode:
        rcParams["text.color"] = "white"  # axes background color
        rcParams["axes.facecolor"] = "white"  # axes background color
        rcParams["axes.edgecolor"] = "white"  # axes edge color
        rcParams["axes.labelcolor"] = "white"
        rcParams["xtick.color"] = "white"  # color of the tick labels
        rcParams["ytick.color"] = "white"  # color of the tick labels
        rcParams["grid.color"] = "white"  # grid color
        rcParams[
            "legend.facecolor"] = "inherit"  # legend background color (when 'inherit' uses axes.facecolor)
        rcParams[
            "legend.edgecolor"] = "white"  # legend edge color (when 'inherit' uses axes.edgecolor)

    rc(
        "text.latex",
        preamble=r"\usepackage{sfmath}",
    )

    # Which signal to plot
    print("")
    print("")
    print("{:#^48}".format(""))
    #if len(input)==1: input = input[0]
    print("Plotting", input)

    #######################
    ####   READ MAP   #####
    #######################

    # Get maps array if .h5 file
    if input.endswith(".h5"):
        from src.commands import h5map2fits
        from src.tools import alm2fits_tool

        # Get maps from alm data in .h5
        if dataset.endswith("alm"):
            print("Converting alms to map")
            (
                maps,
                nsid,
                lmax,
                fwhm,
                outfile,
            ) = alm2fits_tool(
                input,
                dataset,
                nside,
                lmax,
                fwhm,
                save=False,
            )

        # Get maps from map data in .h5
        elif dataset.endswith("map"):
            print("Reading map from h5")
            (
                maps,
                nsid,
                lmax,
                outfile,
            ) = h5map2fits(input, dataset, save=False)

        # Found no data specified kind in .h5
        else:
            print("Dataset not found. Breaking.")
            print(f"Does {input}/{dataset} exist?")
            sys.exit()

    # Plot all signals specified
    print(f"Plotting the following signals: {sig}")
    print("{:#^48}".format(""))
    for polt in sig:
        signal_label = get_signallabel(polt)
        if data is not None:
            m = data.copy()
            m = hp.ma(m)
            nsid = hp.get_nside(m)
            outfile = input.replace(".fits", "")
        else:
            try:
                if input.endswith(".fits"):
                    map, header = hp.read_map(
                        input,
                        field=polt,
                        verbose=False,
                        h=True,
                        dtype=None,
                    )
                    header = dict(header)
                    try:
                        signal_label = header[f"TTYPE{polt+1}"]
                        if signal_label in ["TEMPERATURE", "TEMP"]:
                            signal_label = "T"
                        if signal_label in [
                                "Q-POLARISATION", "Q_POLARISATION"
                        ]:
                            signal_label = "Q"
                        if signal_label in [
                                "U-POLARISATION", "U_POLARISATION"
                        ]:
                            signal_label = "U"

                    except:
                        pass

                    m = hp.ma(map)  # Dont use header for this
                    nsid = hp.get_nside(m)
                    outfile = input.replace(".fits", "")

                elif input.endswith(".h5"):
                    m = maps[polt]
            except:
                print(f"{polt} not found")
                sys.exit()

        ############
        #  SMOOTH  #
        ############
        if fwhm > 0 and input.endswith(".fits"):
            print("")
            print(f"Smoothing fits map to {fwhm} arcmin fwhm")
            print("")
            m = hp.smoothing(
                m,
                fwhm=arcmin2rad(fwhm),
                lmax=lmax,
            )

        ############
        # UD_GRADE #
        ############
        if nside is not None and input.endswith(".fits"):
            if nsid != nside:
                print(f"UDgrading map from {nsid} to {nside}")
                m = hp.ud_grade(
                    m,
                    nside,
                )
        else:
            nside = nsid

        ########################
        #### remove dipole #####
        ########################
        if remove_dipole:
            starttime = time.time()
            print("Removing dipole:")
            dip_mask_name = remove_dipole
            # Mask map for dipole estimation
            m_masked = hp.ma(m)
            m_masked.mask = np.logical_not(
                hp.read_map(
                    dip_mask_name,
                    verbose=False,
                    dtype=None,
                ))

            # Fit dipole to masked map
            mono, dip = hp.fit_dipole(m_masked)
            print(f"Dipole vector: {dip}")
            print(f"Dipole amplitude: {np.sqrt(np.sum(dip ** 2))}")

            # Create dipole template
            nside = int(nside)
            ray = range(hp.nside2npix(nside))
            vecs = hp.pix2vec(nside, ray)
            dipole = np.dot(dip, vecs)

            # Subtract dipole map from data
            m = m - dipole
            print(f"Dipole removal : {(time.time() - starttime)}"
                  ) if verbose else None

        #######################
        #### Auto-param   #####
        #######################
        # Reset these every signal
        tempmin = min
        tempmax = max
        temptitle = title
        templtitle = ltitle
        tempunit = unit
        templogscale = logscale
        tempcmap = cmap

        # ttl, unt and cmb are temporary variables for title, unit and colormap
        if auto:
            (
                _title,
                ticks,
                cmp,
                lgscale,
                scale,
            ) = get_params(
                m,
                outfile,
                polt,
                signal_label,
            )

            # Title
            if _title["stddev"]:
                ttl = _title["param"] + r"$_{\mathrm{" + _title[
                    "comp"] + "}}^{\sigma}$"
            elif _title["mean"]:
                ttl = r"$\langle$" + _title[
                    "param"] + r"$\rangle$" + r"$_{\mathrm{" + _title[
                        "comp"] + "}}^{ }$"
            elif _title["diff"]:
                ttl = r"$\Delta$ " + _title["param"] + r"$_{\mathrm{" + _title[
                    "comp"] + "}}^{" + _title["diff_label"] + "}$"
            else:
                ttl = _title["param"] + r"$_{\mathrm{" + _title[
                    "comp"] + "}}^{ }$"
            # Left signal label
            lttl = r"$" + _title["sig"] + "$"
            if lttl == "$I$":
                lttl = "$T$"
            elif lttl == "$QU$":
                lttl = "$P$"
            #elif lttl == "$P$":
            #    ticks *= 2

            # Tick bug fix
            mn = ticks[0]
            mx = ticks[-1]
            if len(ticks) > 2:
                mid = ticks[1:-1]

            # Unit
            unt = _title["unit"]
        else:
            ttl = ""
            lttl = ""
            unt = ""
            ticks = [False, False]
            cmp = "planck"
            lgscale = False

        # Scale map
        m *= scale

        # If range has been specified, set.
        """
        if rng:
            if rng == "auto":
                if minmax:
                    mn = np.min(m)
                    mx = np.max(m)
                else:
                    mn, mx = get_ticks(m, 97.5)
                if min is False:
                    min = mn
                if max is False:
                    max = mx
            else:
                rng = float(rng)
                min = -rng
                max = rng
            
            ticks = [min, 0.0, max]
            print("hihi",rng)
        else: 
            print("pre", ticks, min, max)
            # If min and max have been specified, set.
            if min is not False:
                ticks[0] = float(min)

            if max is not False:
                ticks[-1] = float(max)
        """
        # If min and max have been specified, set.
        if rng == "auto" and not auto:
            print("Setting range from 97.5th percentile of data")
            mn, mx = get_ticks(m, 97.5)
        elif rng == "minmax":
            print("Setting range from min to max of data")
            mn = np.min(m)
            mx = np.max(m)
        else:
            try:
                if float(rng) > 0.0:
                    mn = -float(rng)
                    mx = float(rng)
                    ticks = [False, 0.0, False]
            except:
                pass

        if min is False:
            min = mn
        else:
            min = float(min)

        if max is False:
            max = mx
        else:
            max = float(max)

        ticks[0] = min
        ticks[-1] = max
        if mid:
            ticks = [min, *mid, max]

        ##########################
        #### Plotting Params #####
        ##########################

        # Upper right title
        if not title:
            title = ttl

        # Upper left title
        if not ltitle:
            ltitle = lttl

        # Unit under colorbar
        if not unit:
            unit = unt

        # Image size -  ratio is always 1/2
        xsize = 2000
        ysize = int(xsize / 2.0)

        ticklabels = ticks
        #######################
        ####   logscale   #####
        #######################
        # Some maps turns on logscale automatically
        # -logscale command overwrites this
        if logscale == None:
            logscale = lgscale

        if logscale:
            print("Applying logscale")
            starttime = time.time()

            m = np.log10(0.5 * (m + np.sqrt(4.0 + m * m)))

            ticks = []
            for i in ticklabels:
                if i > 0:
                    ticks.append(np.log10(i))
                elif i < 0:
                    ticks.append(-np.log10(abs(i)))
                else:
                    ticks.append(i)

            m = np.maximum(np.minimum(m, ticks[-1]), ticks[0])

            print(
                "Logscale",
                (time.time() - starttime),
            ) if verbose else None

        ######################
        #### COLOR SETUP #####
        ######################
        # Chose colormap manually
        if cmap == None:
            # If not defined autoset or goto planck
            cmap = cmp

        if cmap == "planck":
            from pathlib import Path

            cmap = Path(__file__).parent / "parchment1.dat"
            cmap = col.ListedColormap(np.loadtxt(cmap) / 255.0, "planck")
        else:
            try:
                import cmasher
                cmap = eval(f"cmasher.{cmap}")
            except:
                cmap = plt.get_cmap(cmap)

        print(f"Colormap: {cmap.name}")
        #######################
        ####  Projection? #####
        #######################
        theta = np.linspace(np.pi, 0, ysize)
        phi = np.linspace(-np.pi, np.pi, xsize)
        longitude = np.radians(np.linspace(-180, 180, xsize))
        latitude = np.radians(np.linspace(-90, 90, ysize))

        # project the map to a rectangular matrix xsize x ysize
        PHI, THETA = np.meshgrid(phi, theta)
        grid_pix = hp.ang2pix(nside, THETA, PHI)

        ######################
        ######## Mask ########
        ######################
        if mask:
            print(f"Masking using {mask}")
            masked = True

            # Apply mask
            hp.ma(m)
            m.mask = np.logical_not(hp.read_map(mask, field=polt))

            # Don't know what this does, from paperplots by Zonca.
            grid_mask = m.mask[grid_pix]
            grid_map = np.ma.MaskedArray(m[grid_pix], grid_mask)

            if mfill:
                cmap.set_bad(mfill)  # color of missing pixels
                # cmap.set_under("white") # color of background, necessary if you want to use
                # using directly matplotlib instead of mollview has higher quality output
        else:
            grid_map = m[grid_pix]

        ######################
        #### Formatting ######
        ######################
        from matplotlib.projections.geo import GeoAxes

        class ThetaFormatterShiftPi(GeoAxes.ThetaFormatter):
            """Shifts labelling by pi
            Shifts labelling from -180,180 to 0-360"""
            def __call__(self, x, pos=None):
                if x != 0:
                    x *= -1
                if x < 0:
                    x += 2 * np.pi
                return GeoAxes.ThetaFormatter.__call__(self, x, pos)

        sizes = get_sizes(size)
        for width in sizes:
            print("Size: " + str(width))
            height = width / 2.0

            # Make sure text doesnt change with colorbar
            height *= 1.275 if colorbar else 1

            ################
            ##### font #####
            ################
            if width > 12.0:
                fontsize = 8
            elif width == 12.0:
                fontsize = 7
            else:
                fontsize = 6

            fig = plt.figure(figsize=(
                cm2inch(width),
                cm2inch(height),
            ), )
            ax = fig.add_subplot(111, projection="mollweide")

            # rasterized makes the map bitmap while the labels remain vectorial
            # flip longitude to the astro convention
            image = plt.pcolormesh(
                longitude[::-1],
                latitude,
                grid_map,
                vmin=ticks[0],
                vmax=ticks[-1],
                rasterized=True,
                cmap=cmap,
                shading='auto',
            )
            # graticule
            ax.set_longitude_grid(60)
            ax.xaxis.set_major_formatter(ThetaFormatterShiftPi(60))

            if width < 10:
                ax.set_latitude_grid(45)
                ax.set_longitude_grid_ends(90)

            ################
            ### COLORBAR ###
            ################
            if colorbar:
                # colorbar
                from matplotlib.ticker import FuncFormatter

                cb = fig.colorbar(
                    image,
                    orientation="horizontal",
                    shrink=0.3,
                    pad=0.08,
                    ticks=ticks,
                    format=FuncFormatter(fmt),
                )

                # Format tick labels
                print("Ticks: ", ticklabels)
                ticklabels = [fmt(i, 1) for i in ticklabels]
                cb.ax.set_xticklabels(ticklabels)

                cb.ax.xaxis.set_label_text(unit)
                cb.ax.xaxis.label.set_size(fontsize)
                # cb.ax.minorticks_on()

                cb.ax.tick_params(
                    which="both",
                    axis="x",
                    direction="in",
                    labelsize=fontsize,
                )
                cb.ax.xaxis.labelpad = 4  # -11
                # workaround for issue with viewers, see colorbar docstring
                cb.solids.set_edgecolor("face")

            # remove longitude tick labels
            ax.xaxis.set_ticklabels([])
            # remove horizontal grid
            ax.xaxis.set_ticks([])
            ax.yaxis.set_ticklabels([])
            ax.yaxis.set_ticks([])
            plt.grid(True)

            ###################
            ## RIGHT TITLE ####
            ###################
            plt.text(
                6.0,
                1.3,
                r"%s" % title,
                ha="center",
                va="center",
                fontsize=fontsize,
            )

            ##################
            ## LEFT TITLE ####
            ##################
            plt.text(
                -6.0,
                1.3,
                r"%s" % ltitle,
                ha="center",
                va="center",
                fontsize=fontsize,
            )

            ##############
            #### SAVE ####
            ##############
            plt.tight_layout()
            filetype = "png" if png else "pdf"
            # Turn on transparency unless told otherwise
            tp = False if white_background else True

            ##############
            ## filename ##
            ##############
            print(f"Signal label: {signal_label}")

            outfile = outfile.replace("_IQU_", "_")
            outfile = outfile.replace("_I_", "_")

            filename = []
            filename.append(f"{str(int(fwhm))}arcmin") if fwhm > 0 else None
            filename.append("cb") if colorbar else None
            filename.append("masked") if masked else None
            filename.append("nodip") if remove_dipole else None
            filename.append("dark") if darkmode else None
            filename.append(f"c-{cmap.name}")

            nside_tag = "_n" + str(int(nside))
            if nside_tag in outfile:
                outfile = outfile.replace(nside_tag, "")

            fn = outfile + f"_{signal_label}_w{str(int(width))}" + nside_tag

            for i in filename:
                fn += f"_{i}"
            fn += f".{filetype}"

            starttime = time.time()
            if outdir:
                fn = outdir + "/" + os.path.split(fn)[-1]

            print(f"Output: {fn}")
            plt.savefig(
                fn,
                bbox_inches="tight",
                pad_inches=0.02,
                transparent=tp,
                format=filetype,
            )
            print(
                "Savefig",
                (time.time() - starttime),
            ) if verbose else None

            plt.close()
            print(
                "Totaltime:",
                (time.time() - totaltime),
            ) if verbose else None

        min = tempmin
        max = tempmax
        title = temptitle
        ltitle = temptitle
        unit = tempunit
        logscale = templogscale
        cmap = tempcmap
コード例 #7
0
def release(ctx, chain, burnin, procver, resamp, copy_, freqmaps, ame, ff, cmb,
            synch, dust, br, diff, diffcmb, goodness, chisq, res, all_, plot):
    """
    Creates a release file-set on the BeyondPlanck format.
    https://gitlab.com/BeyondPlanck/repo/-/wikis/BeyondPlanck-Release-Candidate-2

    ex. c3pp release chains_v1_c{1,2}/chain_c000{1,2}.h5 30 BP_r1
    Will output formatted files using all chains specified,
    with a burnin of 30 to a directory called BP_r1

    This function outputs the following files to the {procver} directory:
    BP_chain01_full_{procver}.h5
    BP_resamp_chain01_full_Cl_{procver}.h5
    BP_resamp_chain01_full_noCl_{procver}.h5
    BP_param_full_v1.txt
    BP_param_resamp_Cl_v1.txt
    BP_param_resamp_noCl_v1.txt

    BP_030_IQU_full_n0512_{procver}.fits
    BP_044_IQU_full_n0512_{procver}.fits
    BP_070_IQU_full_n1024_{procver}.fits

    BP_cmb_IQU_full_n1024_{procver}.fits
    BP_synch_IQU_full_n1024_{procver}.fits
    BP_freefree_I_full_n1024_{procver}.fits
    BP_ame_I_full_n1024_{procver}.fits

    BP_cmb_GBRlike_{procver}.fits
    """
    # TODO
    # Use proper masks for output of CMB component
    # Use inpainted data as well in CMB component

    from src.fitsformatter import format_fits, get_data, get_header
    from pathlib import Path
    import shutil

    if all_:  # sets all other flags to true
        copy_ = not copy_
        freqmaps = not freqmaps
        ame = not ame
        ff = not ff
        cmb = not cmb
        synch = not synch
        dust = not dust
        br = not br
        diff = not diff
        diffcmb = not diffcmb
        goodness = not goodness
        res = not res
        chisq = not chisq

    if goodness:
        chisq = res = True
    elif chisq or res:
        goodness = True

    # Make procver directory if not exists
    click.echo("{:#^80}".format(""))
    click.echo(f"Creating directory {procver}")
    Path(procver).mkdir(parents=True, exist_ok=True)
    chains = chain
    maxchain = len(chains)
    """
    Copying chains files
    """
    if copy_:
        # Commander3 parameter file for main chain
        for i, chainfile in enumerate(chains, 1):
            path = os.path.split(chainfile)[0]
            for file in os.listdir(path):
                if file.startswith("param") and i == 1:  # Copy only first
                    click.echo(
                        f"Copying {path}/{file} to {procver}/BP_param_full_c" +
                        str(i).zfill(4) + ".txt")
                    if resamp:
                        shutil.copyfile(
                            f"{path}/{file}",
                            f"{procver}/BP_param_resamp_Cl_c" +
                            str(i).zfill(4) + ".txt",
                        )
                    else:
                        shutil.copyfile(
                            f"{path}/{file}",
                            f"{procver}/BP_param_full_c" + str(i).zfill(4) +
                            ".txt",
                        )

            if resamp:
                # Resampled CMB-only full-mission Gibbs chain file with Cls (for BR estimator)
                click.echo(f"Copying {chainfile} to {procver}/BP_resamp_c" +
                           str(i).zfill(4) + f"_full_Cl_{procver}.h5")
                shutil.copyfile(
                    chainfile,
                    f"{procver}/BP_resamp_c" + str(i).zfill(4) +
                    f"_full_Cl_{procver}.h5",
                )
            else:
                # Full-mission Gibbs chain file
                click.echo(f"Copying {chainfile} to {procver}/BP_c" +
                           str(i).zfill(4) + f"_full_{procver}.h5")
                shutil.copyfile(
                    chainfile,
                    f"{procver}/BP_c" + str(i).zfill(4) +
                    f"_full_{procver}.h5",
                )

    #if halfring:
    #   # Copy halfring files
    #   for i, chainfile in enumerate([halfring], 1):
    #       # Copy halfring files
    #       click.echo(f"Copying {resamp} to {procver}/BP_halfring_c" + str(i).zfill(4) + f"_full_Cl_{procver}.h5")
    #       shutil.copyfile(halfring, f"{procver}/BP_halfring_c" + str(i).zfill(4) + f"_full_Cl_{procver}.h5",)
    """
    IQU mean, IQU stdev, (Masks for cmb)
    Run mean and stddev from min to max sample (Choose min manually or start at 1?)
    """
    if resamp:
        chain = f"{procver}/BP_resamp_c0001_full_Cl_{procver}.h5"
    else:
        chain = f"{procver}/BP_c0001_full_{procver}.h5"
    if freqmaps:
        try:
            # Full-mission 30 GHz IQU frequency map
            # BP_030_IQU_full_n0512_{procver}.fits
            format_fits(
                chain=chain,
                extname="FREQMAP",
                types=[
                    "I_MEAN",
                    "Q_MEAN",
                    "U_MEAN",
                    "I_RMS",
                    "Q_RMS",
                    "U_RMS",
                    "I_STDDEV",
                    "Q_STDDEV",
                    "U_STDDEV",
                ],
                units=[
                    "uK",
                    "uK",
                    "uK",
                    "uK",
                    "uK",
                    "uK",
                    "uK",
                    "uK",
                    "uK",
                ],
                nside=512,
                burnin=burnin,
                maxchain=maxchain,
                polar=True,
                component="030",
                fwhm=0.0,
                nu_ref_t="30.0 GHz",
                nu_ref_p="30.0 GHz",
                procver=procver,
                filename=f"BP_030_IQU_full_n0512_{procver}.fits",
                bndctr=30,
                restfreq=28.456,
                bndwid=9.899,
            )
            # Full-mission 44 GHz IQU frequency map
            format_fits(
                chain=chain,
                extname="FREQMAP",
                types=[
                    "I_MEAN",
                    "Q_MEAN",
                    "U_MEAN",
                    "I_RMS",
                    "Q_RMS",
                    "U_RMS",
                    "I_STDDEV",
                    "Q_STDDEV",
                    "U_STDDEV",
                ],
                units=[
                    "uK",
                    "uK",
                    "uK",
                    "uK",
                    "uK",
                    "uK",
                    "uK",
                    "uK",
                    "uK",
                ],
                nside=512,
                burnin=burnin,
                maxchain=maxchain,
                polar=True,
                component="044",
                fwhm=0.0,
                nu_ref_t="44.0 GHz",
                nu_ref_p="44.0 GHz",
                procver=procver,
                filename=f"BP_044_IQU_full_n0512_{procver}.fits",
                bndctr=44,
                restfreq=44.121,
                bndwid=10.719,
            )
            # Full-mission 70 GHz IQU frequency map
            format_fits(
                chain=chain,
                extname="FREQMAP",
                types=[
                    "I_MEAN",
                    "Q_MEAN",
                    "U_MEAN",
                    "I_RMS",
                    "Q_RMS",
                    "U_RMS",
                    "I_STDDEV",
                    "Q_STDDEV",
                    "U_STDDEV",
                ],
                units=[
                    "uK",
                    "uK",
                    "uK",
                    "uK",
                    "uK",
                    "uK",
                    "uK",
                    "uK",
                    "uK",
                ],
                nside=1024,
                burnin=burnin,
                maxchain=maxchain,
                polar=True,
                component="070",
                fwhm=0.0,
                nu_ref_t="70.0 GHz",
                nu_ref_p="70.0 GHz",
                procver=procver,
                filename=f"BP_070_IQU_full_n1024_{procver}.fits",
                bndctr=70,
                restfreq=70.467,
                bndwid=14.909,
            )

        except Exception as e:
            print(e)
            click.secho("Continuing...", fg="yellow")
    """
    FOREGROUND MAPS
    """
    # Full-mission CMB IQU map
    if cmb:
        if resamp:
            try:
                format_fits(
                    chain,
                    extname="COMP-MAP-CMB-RESAMP",
                    types=[
                        "I_MEAN",
                        "I_STDDEV",
                    ],
                    units=[
                        "uK_cmb",
                        "uK_cmb",
                    ],
                    nside=1024,
                    burnin=burnin,
                    maxchain=maxchain,
                    polar=True,
                    component="CMB",
                    fwhm=14.0,
                    nu_ref_t="NONE",
                    nu_ref_p="NONE",
                    procver=procver,
                    filename=f"BP_cmb_resamp_IQU_full_n1024_{procver}.fits",
                    bndctr=None,
                    restfreq=None,
                    bndwid=None,
                )
            except Exception as e:
                print(e)
                click.secho("Continuing...", fg="yellow")

        else:
            try:
                format_fits(
                    chain,
                    extname="COMP-MAP-CMB",
                    types=[
                        "I_MEAN",
                        "Q_MEAN",
                        "U_MEAN",
                        "I_STDDEV",
                        "Q_STDDEV",
                        "U_STDDEV",
                        "mask1",
                        "mask2",
                    ],
                    units=[
                        "uK_cmb",
                        "uK_cmb",
                        "uK",
                        "uK",
                        "NONE",
                        "NONE",
                    ],
                    nside=1024,
                    burnin=burnin,
                    maxchain=maxchain,
                    polar=True,
                    component="CMB",
                    fwhm=14.0,
                    nu_ref_t="NONE",
                    nu_ref_p="NONE",
                    procver=procver,
                    filename=f"BP_cmb_IQU_full_n1024_{procver}.fits",
                    bndctr=None,
                    restfreq=None,
                    bndwid=None,
                )
            except Exception as e:
                print(e)
                click.secho("Continuing...", fg="yellow")

    if ff:
        try:
            # Full-mission free-free I map
            format_fits(
                chain,
                extname="COMP-MAP-FREE-FREE",
                types=[
                    "I_MEAN",
                    "I_TE_MEAN",
                    "I_STDDEV",
                    "I_TE_STDDEV",
                ],
                units=[
                    "uK_RJ",
                    "K",
                    "uK_RJ",
                    "K",
                ],
                nside=1024,
                burnin=burnin,
                maxchain=maxchain,
                polar=False,
                component="FREE-FREE",
                fwhm=30.0,
                nu_ref_t="40.0 GHz",
                nu_ref_p="40.0 GHz",
                procver=procver,
                filename=f"BP_freefree_I_full_n1024_{procver}.fits",
                bndctr=None,
                restfreq=None,
                bndwid=None,
            )
        except Exception as e:
            print(e)
            click.secho("Continuing...", fg="yellow")

    if ame:
        try:
            # Full-mission AME I map
            format_fits(
                chain,
                extname="COMP-MAP-AME",
                types=[
                    "I_MEAN",
                    "I_NU_P_MEAN",
                    "I_STDDEV",
                    "I_NU_P_STDDEV",
                ],
                units=[
                    "uK_RJ",
                    "GHz",
                    "uK_RJ",
                    "GHz",
                ],
                nside=1024,
                burnin=burnin,
                maxchain=maxchain,
                polar=False,
                component="AME",
                fwhm=120.0,
                nu_ref_t="22.0 GHz",
                nu_ref_p="22.0 GHz",
                procver=procver,
                filename=f"BP_ame_I_full_n1024_{procver}.fits",
                bndctr=None,
                restfreq=None,
                bndwid=None,
            )
        except Exception as e:
            print(e)
            click.secho("Continuing...", fg="yellow")

    if synch:
        try:
            # Full-mission synchrotron IQU map
            format_fits(
                chain,
                extname="COMP-MAP-SYNCHROTRON",
                types=[
                    "I_MEAN",
                    "Q_MEAN",
                    "U_MEAN",
                    "P_MEAN",
                    "I_BETA_MEAN",
                    "QU_BETA_MEAN",
                    "I_STDDEV",
                    "Q_STDDEV",
                    "U_STDDEV",
                    "P_STDDEV",
                    "I_BETA_STDDEV",
                    "QU_BETA_STDDEV",
                ],
                units=[
                    "uK_RJ",
                    "uK_RJ",
                    "uK_RJ",
                    "uK_RJ",
                    "NONE",
                    "NONE",
                    "uK_RJ",
                    "uK_RJ",
                    "uK_RJ",
                    "uK_RJ",
                    "NONE",
                    "NONE",
                ],
                nside=1024,
                burnin=burnin,
                maxchain=maxchain,
                polar=True,
                component="SYNCHROTRON",
                fwhm=60.0,  # 60.0,
                nu_ref_t="30.0 GHz",
                nu_ref_p="30.0 GHz",
                procver=procver,
                filename=f"BP_synch_IQU_full_n1024_{procver}.fits",
                bndctr=None,
                restfreq=None,
                bndwid=None,
            )
        except Exception as e:
            print(e)
            click.secho("Continuing...", fg="yellow")

    if dust:
        try:
            # Full-mission thermal dust IQU map
            format_fits(
                chain,
                extname="COMP-MAP-DUST",
                types=[
                    "I_MEAN",
                    "Q_MEAN",
                    "U_MEAN",
                    "P_MEAN",
                    "I_BETA_MEAN",
                    "QU_BETA_MEAN",
                    "I_T_MEAN",
                    "QU_T_MEAN",
                    "I_STDDEV",
                    "Q_STDDEV",
                    "U_STDDEV",
                    "P_STDDEV",
                    "I_BETA_STDDEV",
                    "QU_BETA_STDDEV",
                    "I_T_STDDEV",
                    "QU_T_STDDEV",
                ],
                units=[
                    "uK_RJ",
                    "uK_RJ",
                    "uK_RJ",
                    "uK_RJ",
                    "NONE",
                    "NONE",
                    "K",
                    "K",
                    "uK_RJ",
                    "uK_RJ",
                    "uK_RJ",
                    "uK_RJ",
                    "NONE",
                    "NONE",
                    "K",
                    "K",
                ],
                nside=1024,
                burnin=burnin,
                maxchain=maxchain,
                polar=True,
                component="DUST",
                fwhm=10.0,  # 60.0,
                nu_ref_t="545 GHz",
                nu_ref_p="353 GHz",
                procver=procver,
                filename=f"BP_dust_IQU_full_n1024_{procver}.fits",
                bndctr=None,
                restfreq=None,
                bndwid=None,
            )
        except Exception as e:
            print(e)
            click.secho("Continuing...", fg="yellow")

    if diff:
        import healpy as hp
        try:
            click.echo("Creating frequency difference maps")
            path_dx12 = "/mn/stornext/u3/trygvels/compsep/cdata/like/BP_releases/dx12"
            path_npipe = "/mn/stornext/u3/trygvels/compsep/cdata/like/BP_releases/npipe"
            maps_dx12 = [
                "30ghz_2018_n1024_beamscaled_dip.fits",
                "44ghz_2018_n1024_beamscaled_dip.fits",
                "70ghz_2018_n1024_beamscaled_dip.fits"
            ]
            maps_npipe = [
                "npipe6v20_030_map_uK.fits",
                "npipe6v20_044_map_uK.fits",
                "npipe6v20_070_map_uK.fits",
            ]
            maps_BP = [
                f"BP_030_IQU_full_n0512_{procver}.fits",
                f"BP_044_IQU_full_n0512_{procver}.fits",
                f"BP_070_IQU_full_n1024_{procver}.fits",
            ]
            beamscaling = [9.8961854E-01, 9.9757886E-01, 9.9113965E-01]
            for i, freq in enumerate([
                    "030",
                    "044",
                    "070",
            ]):
                map_BP = hp.read_map(f"{procver}/{maps_BP[i]}",
                                     field=(0, 1, 2),
                                     verbose=False,
                                     dtype=None)
                map_npipe = hp.read_map(f"{path_npipe}/{maps_npipe[i]}",
                                        field=(0, 1, 2),
                                        verbose=False,
                                        dtype=None)
                map_dx12 = hp.read_map(f"{path_dx12}/{maps_dx12[i]}",
                                       field=(0, 1, 2),
                                       verbose=False,
                                       dtype=None)

                #dx12 dipole values:
                # 3362.08 pm 0.99, 264.021 pm 0.011, 48.253 ± 0.005
                # 233.18308357  2226.43833645 -2508.42179665
                #dipole_dx12 = -3362.08*hp.dir2vec(264.021, 48.253, lonlat=True)

                #map_dx12  = map_dx12/beamscaling[i]
                # Smooth to 60 arcmin
                map_BP = hp.smoothing(map_BP,
                                      fwhm=arcmin2rad(60.0),
                                      verbose=False)
                map_npipe = hp.smoothing(map_npipe,
                                         fwhm=arcmin2rad(60.0),
                                         verbose=False)
                map_dx12 = hp.smoothing(map_dx12,
                                        fwhm=arcmin2rad(60.0),
                                        verbose=False)

                #ud_grade 30 and 44ghz
                if i < 2:
                    map_npipe = hp.ud_grade(
                        map_npipe,
                        nside_out=512,
                    )
                    map_dx12 = hp.ud_grade(
                        map_dx12,
                        nside_out=512,
                    )

                # Remove monopoles
                map_BP -= np.mean(map_BP, axis=1).reshape(-1, 1)
                map_npipe -= np.mean(map_npipe, axis=1).reshape(-1, 1)
                map_dx12 -= np.mean(map_dx12, axis=1).reshape(-1, 1)

                hp.write_map(f"{procver}/BP_{freq}_diff_npipe_{procver}.fits",
                             np.array(map_BP - map_npipe),
                             overwrite=True,
                             column_names=["I_DIFF", "Q_DIFF", "U_DIFF"],
                             dtype=None)
                hp.write_map(f"{procver}/BP_{freq}_diff_dx12_{procver}.fits",
                             np.array(map_BP - map_dx12),
                             overwrite=True,
                             column_names=["I_DIFF", "Q_DIFF", "U_DIFF"],
                             dtype=None)

        except Exception as e:
            print(e)
            click.secho("Continuing...", fg="yellow")

    if diffcmb:
        import healpy as hp
        try:
            click.echo("Creating cmb difference maps")
            path_cmblegacy = "/mn/stornext/u3/trygvels/compsep/cdata/like/BP_releases/cmb-legacy"
            mask_ = hp.read_map(
                "/mn/stornext/u3/trygvels/compsep/cdata/like/BP_releases/masks/dx12_v3_common_mask_int_005a_1024_TQU.fits",
                verbose=False,
                dtype=np.bool,
            )
            map_BP = hp.read_map(
                f"{procver}/BP_cmb_IQU_full_n1024_{procver}.fits",
                field=(0, 1, 2),
                verbose=False,
                dtype=None,
            )
            map_BP_masked = hp.ma(map_BP[0])
            map_BP_masked.mask = np.logical_not(mask_)
            mono, dip = hp.fit_dipole(map_BP_masked)
            nside = 1024
            ray = range(hp.nside2npix(nside))
            vecs = hp.pix2vec(nside, ray)
            dipole = np.dot(dip, vecs)
            map_BP[0] = map_BP[0] - dipole - mono
            map_BP = hp.smoothing(map_BP,
                                  fwhm=arcmin2rad(np.sqrt(60.0**2 - 14**2)),
                                  verbose=False)
            #map_BP -= np.mean(map_BP,axis=1).reshape(-1,1)
            for i, method in enumerate([
                    "commander",
                    "sevem",
                    "nilc",
                    "smica",
            ]):

                data = f"COM_CMB_IQU-{method}_2048_R3.00_full.fits"
                click.echo(f"making difference map with {data}")
                map_cmblegacy = hp.read_map(f"{path_cmblegacy}/{data}",
                                            field=(0, 1, 2),
                                            verbose=False,
                                            dtype=None)
                map_cmblegacy = hp.smoothing(map_cmblegacy,
                                             fwhm=arcmin2rad(60.0),
                                             verbose=False)
                map_cmblegacy = hp.ud_grade(
                    map_cmblegacy,
                    nside_out=1024,
                )
                map_cmblegacy = map_cmblegacy * 1e6

                # Remove monopoles
                map_cmblegacy_masked = hp.ma(map_cmblegacy[0])
                map_cmblegacy_masked.mask = np.logical_not(mask_)
                mono = hp.fit_monopole(map_cmblegacy_masked)
                click.echo(f"{method} subtracting monopole {mono}")
                map_cmblegacy[0] = map_cmblegacy[
                    0] - mono  #np.mean(map_cmblegacy,axis=1).reshape(-1,1)

                hp.write_map(f"{procver}/BP_cmb_diff_{method}_{procver}.fits",
                             np.array(map_BP - map_cmblegacy),
                             overwrite=True,
                             column_names=["I_DIFF", "Q_DIFF", "U_DIFF"],
                             dtype=None)

        except Exception as e:
            print(e)
            click.secho("Continuing...", fg="yellow")

    if goodness:
        import healpy as hp
        path_goodness = procver + "/goodness"
        Path(path_goodness).mkdir(parents=True, exist_ok=True)
        print("PATH", path_goodness)

        cmin = int(os.path.split(chains[0])[0].rsplit("_c")[-1])
        cmax = int(os.path.split(chains[-1])[0].rsplit("_c")[-1])
        chdir = os.path.split(chains[0])[0].rsplit("_", 1)[0]

        if chisq:
            try:
                format_fits(
                    chains,
                    extname="CHISQ",
                    types=[
                        "I_MEAN",
                        "P_MEAN",
                    ],
                    units=[
                        "NONE",
                        "NONE",
                    ],
                    nside=16,
                    burnin=burnin,
                    maxchain=maxchain,
                    polar=True,
                    component="CHISQ",
                    fwhm=0.0,
                    nu_ref_t="NONE",
                    nu_ref_p="NONE",
                    procver=procver,
                    filename=f'goodness/BP_chisq_n16_{procver}.fits',
                    bndctr=None,
                    restfreq=None,
                    bndwid=None,
                    cmin=cmin,
                    cmax=cmax,
                    chdir=chdir,
                )
            except Exception as e:
                print(e)
                click.secho("Continuing...", fg="yellow")

        if res:
            click.echo("Save and format chisq map and residual maps")
            bands = {
                "030": {
                    "nside": 512,
                    "fwhm": 120,
                    "sig": "IQU",
                    "fields": (0, 1, 2),
                    "unit": "uK",
                    "scale": 1.,
                },
                "044": {
                    "nside": 512,
                    "fwhm": 120,
                    "sig": "IQU",
                    "fields": (0, 1, 2),
                    "unit": "uK",
                    "scale": 1.,
                },
                "070": {
                    "nside": 1024,
                    "fwhm": 120,
                    "sig": "IQU",
                    "fields": (0, 1, 2),
                    "unit": "uK",
                    "scale": 1.,
                },
                "030-WMAP_Ka": {
                    "nside": 512,
                    "fwhm": 120,
                    "sig": "I",
                    "fields": (0, ),
                    "unit": "uK",
                    "scale": 1e3,
                },
                "040-WMAP_Q1": {
                    "nside": 512,
                    "fwhm": 120,
                    "sig": "I",
                    "fields": (0, ),
                    "unit": "uK",
                    "scale": 1.,
                },
                "040-WMAP_Q2": {
                    "nside": 512,
                    "fwhm": 120,
                    "sig": "I",
                    "fields": (0, ),
                    "unit": "uK",
                    "scale": 1.,
                },
                "060-WMAP_V1": {
                    "nside": 512,
                    "fwhm": 120,
                    "sig": "I",
                    "fields": (0, ),
                    "unit": "uK",
                    "scale": 1.,
                },
                "060-WMAP_V2": {
                    "nside": 512,
                    "fwhm": 120,
                    "sig": "I",
                    "fields": (0, ),
                    "unit": "uK",
                    "scale": 1.,
                },
                "0.4-Haslam": {
                    "nside": 512,
                    "fwhm": 120,
                    "sig": "I",
                    "fields": (0, ),
                    "unit": "uK",
                    "scale": 1.,
                },
                "857": {
                    "nside": 1024,
                    "fwhm": 120,
                    "sig": "I",
                    "fields": (0, ),
                    "unit": "uK",
                    "scale": 1.,
                },
                "033-WMAP_Ka_P": {
                    "nside": 16,
                    "fwhm": 0,
                    "sig": "QU",
                    "fields": (1, 2),
                    "unit": "uK",
                    "scale": 1e3,
                },
                "041-WMAP_Q_P": {
                    "nside": 16,
                    "fwhm": 0,
                    "sig": "QU",
                    "fields": (1, 2),
                    "unit": "uK",
                    "scale": 1e3,
                },
                "061-WMAP_V_P": {
                    "nside": 16,
                    "fwhm": 0,
                    "sig": "QU",
                    "fields": (1, 2),
                    "unit": "uK",
                    "scale": 1e3,
                },
                "353": {
                    "nside": 1024,
                    "fwhm": 120,
                    "sig": "QU",
                    "fields": (1, 2),
                    "unit": "uK",
                    "scale": 1.,
                },
            }

            for label, b in bands.items():

                types = []
                units = []
                for l in b["sig"]:
                    types.append(f'{l}_MEAN')
                    units.append(b["unit"])
                for l in b["sig"]:
                    types.append(f'{l}_STDDEV')
                    units.append(b["unit"])
                try:
                    format_fits(
                        chains,
                        extname="FREQBAND_RES",
                        types=types,
                        units=units,
                        nside=b["nside"],
                        burnin=burnin,
                        maxchain=maxchain,
                        polar=True,
                        component=label,
                        fwhm=b["fwhm"],
                        nu_ref_t="NONE",
                        nu_ref_p="NONE",
                        procver=procver,
                        filename=
                        f'goodness/BP_res_{label}_{b["sig"]}_full_n{b["nside"]}_{b["fwhm"]}arcmin_{b["unit"]}_{procver}.fits',
                        bndctr=None,
                        restfreq=None,
                        bndwid=None,
                        cmin=cmin,
                        cmax=cmax,
                        chdir=chdir,
                        fields=b["fields"],
                        scale=b["scale"],
                    )
                except Exception as e:
                    print(e)
                    click.secho("Continuing...", fg="yellow")
    """ As implemented by Simone
    """
    if br and resamp:
        # Gaussianized TT Blackwell-Rao input file
        click.echo("{:-^50}".format("CMB GBR"))
        ctx.invoke(
            sigma_l2fits,
            filename=resamp,
            nchains=1,
            burnin=burnin,
            path="cmb/sigma_l",
            outname=f"{procver}/BP_cmb_GBRlike_{procver}.fits",
            save=True,
        )
    """
    TODO Generalize this so that they can be generated by Elina and Anna-Stiina
    """
    # Full-mission 30 GHz IQU beam symmetrized frequency map
    # BP_030_IQUdeconv_full_n0512_{procver}.fits
    # Full-mission 44 GHz IQU beam symmetrized frequency map
    # BP_044_IQUdeconv_full_n0512_{procver}.fits
    # Full-mission 70 GHz IQU beam symmetrized frequency map
    # BP_070_IQUdeconv_full_n1024_{procver}.fits
    """ Both sigma_l's and Dl's re in the h5. (Which one do we use?)
    """
    # CMB TT, TE, EE power spectrum
    # BP_cmb_Cl_{procver}.txt
    """ Just get this from somewhere
    """
    # Best-fit LCDM CMB TT, TE, EE power spectrum
    # BP_cmb_bfLCDM_{procver}.txt

    if plot:
        os.chdir(procver)
        ctx.invoke(plotrelease, procver=procver, all_=True)
コード例 #8
0
ファイル: healpytut.py プロジェクト: zonca/healpytut
#! http://lambda.gsfc.nasa.gov/data/map/dr4/skymaps/7yr/raw/wmap_band_imap_r9_7yr_W_v4.fits

filename = 'wmap_band_imap_r9_7yr_W_v4.fits'
#filename = '/global/scratch/sd/planck/user/zonca/healpytut/wmap_band_imap_r9_7yr_W_v4.fits'
m = healpy.read_map(filename) #by default converts to RING!!
healpy.mollview(m, title='Histogram equalized', nest=False, norm='hist')
show()
m = healpy.read_map(filename, nest=True) #keeps nested
healpy.mollview(m, coord=['G','E'], title='Linear scale', unit='mK', nest=True, min=-1,max=1, xsize=2000) #xsize increases resolution
healpy.graticule()
show()

healpy.gnomview(m, rot=[0,0.3], title='Linear scale', unit='mK', format='%.2g', nest=True)
show()

print(healpy.fit_dipole(m, gal_cut=20)) # degrees

#!Smoothing
#!~~~~~~~~~

m_smoothed = healpy.smoothing(m, fwhm=60, arcmin=True)
healpy.mollview(m_smoothed, min=-1, max=1, title='Map smoothed 1 deg')

#!Rotator
#!~~~~~~~

rot = healpy.Rotator(coord=['G','E'])
theta_gal, phi_gal = np.pi/2., 0.
theta_ecl, phi_ecl = rot(theta_gal, phi_gal)
print(theta_ecl, phi_ecl)
コード例 #9
0
def Plotter(input, dataset, nside, auto, min, max, mid, rng, colorbar, lmax, fwhm, mask, mfill, sig, remove_dipole, remove_monopole, logscale, size, white_background, darkmode, png, cmap, title, ltitle, unit, scale, outdir, verbose, data, labelsize):
    dpi = 150
    rcParams["backend"] = "agg" if png else "pdf"
    rcParams["legend.fancybox"] = True
    rcParams["lines.linewidth"] = 2
    rcParams["savefig.dpi"] = dpi #300
    rcParams["axes.linewidth"] = 1

    masked = False

    if darkmode:
        rcParams["text.color"] = "white"  # axes background color
        rcParams["axes.facecolor"] = "white"  # axes background color
        rcParams["axes.edgecolor"] = "white"  # axes edge color
        rcParams["axes.labelcolor"] = "white"
        rcParams["xtick.color"] = "white"  # color of the tick labels
        rcParams["ytick.color"] = "white"  # color of the tick labels
        rcParams["grid.color"] = "white"  # grid color
        rcParams["legend.facecolor"] = "inherit"  # legend background color (when 'inherit' uses axes.facecolor)
        rcParams["legend.edgecolor"] = "white"  # legend edge color (when 'inherit' uses axes.edgecolor)

    rc("text.latex", preamble=r"\usepackage{sfmath}",)

    # Which signal to plot
    click.echo("")
    click.echo(click.style("{:#^48}".format(""), fg="green"))
    click.echo(click.style("Plotting",fg="green") + f" {input}")

    #######################
    ####   READ MAP   #####
    #######################

    # Get maps array if .h5 file
    if input.endswith(".h5"):
        from src.commands_hdf import h5map2fits
        from src.tools import alm2fits_tool

        # Get maps from alm data in .h5
        if dataset.endswith("alm"):
            click.echo(click.style("Converting alms to map",fg="green"))
            (maps, nsid, lmax, fwhm, outfile,) = alm2fits_tool(input, dataset, nside, lmax, fwhm, save=False,)

        # Get maps from map data in .h5
        elif dataset.endswith("map"):
            click.echo(click.style("Reading map from hdf",fg="green"))
            (maps, nsid, lmax, outfile,) = h5map2fits(input, dataset, save=False)

        # Found no data specified kind in .h5
        else:
            click.echo(click.style("Dataset not found. Breaking.",fg="red"))
            click.echo(click.style(f"Does {input}/{dataset} exist?",fg="red"))
            sys.exit()

    # Plot all signals specified
    click.echo(click.style("Using signals ",fg="green") + f"{sig}")
    click.echo(click.style("{:#^48}".format(""), fg="green"))
    for polt in sig:
        signal_label = get_signallabel(polt)
        if data is not None:
            m = data.copy()
            m = hp.ma(m)
            nsid = hp.get_nside(m)
            outfile = input.replace(".fits", "")
        else:
            try:
                if input.endswith(".fits"):
                    map, header = hp.read_map(input, field=polt, verbose=False, h=True, dtype=None,)
                    header = dict(header)
                    try:
                        signal_label = header[f"TTYPE{polt+1}"]
                        if signal_label in ["TEMPERATURE", "TEMP"]:
                            signal_label = "T"
                        if signal_label in ["Q-POLARISATION", "Q_POLARISATION"]:
                            signal_label = "Q"
                        if signal_label in ["U-POLARISATION", "U_POLARISATION"]:
                            signal_label = "U"
                        
                    except:
                        pass
            
                    m = hp.ma(map)  # Dont use header for this
                    nsid = hp.get_nside(m)
                    outfile = input.replace(".fits", "")
            
                elif input.endswith(".h5"):
                    m = maps[polt]
            except:
                click.echo(click.style(f"{polt} not found",fg="red"))
                sys.exit()
        
        ############
        #  SMOOTH  #
        ############
        if float(fwhm) > 0 and input.endswith(".fits"):
            click.echo(click.style(f"Smoothing fits map to {fwhm} arcmin fwhm",fg="yellow"))
            m = hp.smoothing(m, fwhm=arcmin2rad(fwhm), lmax=lmax,)

        ############
        # UD_GRADE #
        ############
        if nside is not None and input.endswith(".fits"):
            if nsid != nside:
                click.echo(click.style(f"UDgrading map from {nsid} to {nside}", fg="yellow"))
                m = hp.ud_grade(m, nside,)
        else:
            nside = nsid

        ########################
        #### remove dipole #####
        ########################
        if remove_dipole or remove_monopole:
            starttime = time.time()

            if remove_monopole:
                dip_mask_name = remove_monopole
            if remove_dipole:
                dip_mask_name = remove_dipole
            # Mask map for dipole estimation
            if dip_mask_name == 'auto':
                mono, dip = hp.fit_dipole(m, gal_cut=30)
            else:
                m_masked = hp.ma(m)
                m_masked.mask = np.logical_not(hp.read_map(dip_mask_name,verbose=False,dtype=None,))

                # Fit dipole to masked map
                mono, dip = hp.fit_dipole(m_masked)

            # Subtract dipole map from data
            if remove_dipole:
                click.echo(click.style("Removing dipole:", fg="yellow"))
                click.echo(click.style("Dipole vector:",fg="green") + f" {dip}")
                click.echo(click.style("Dipole amplitude:",fg="green") + f" {np.sqrt(np.sum(dip ** 2))}")

                # Create dipole template
                nside = int(nside)
                ray = range(hp.nside2npix(nside))
                vecs = hp.pix2vec(nside, ray)
                dipole = np.dot(dip, vecs)
                
                m = m - dipole
            if remove_monopole:
                click.echo(click.style("Removing monopole:", fg="yellow"))
                click.echo(click.style("Mono:",fg="green") + f" {mono}")
                m = m - mono
            
            click.echo(f"Dipole removal : {(time.time() - starttime)}") if verbose else None

        #######################
        #### Auto-param   #####
        #######################
        # Reset these every signal
        tempmin = min
        tempmax = max
        tempmid = mid
        temptitle = title
        templtitle = ltitle
        tempunit = unit
        templogscale = logscale
        tempcmap = cmap

        # Scale map
        if scale:
            if "chisq" in outfile:
                click.echo(click.style(f"Scaling chisq data with dof={scale}",fg="yellow"))
                m = (m-scale)/np.sqrt(2*scale)
            else:
                click.echo(click.style(f"Scaling data by {scale}",fg="yellow"))
                m *= scale

        if auto:
            (_title, ticks, cmp, lgscale,) = get_params(m, outfile, polt, signal_label,)
            # Title
            if _title["stddev"]:
                if _title["special"]:
                    ttl =   r"$\sigma_{\mathrm{" + _title["param"].replace("$","") + "}}$"
                else:
                    #_title["param"] + r"$_{\mathrm{" + _title["comp"] + "}}^{\sigma}$" 
                    ttl =   r"$\sigma_{\mathrm{" + _title["comp"] + "}}$"
            elif _title["rms"]:
                ttl =  _title["param"] + r"$_{\mathrm{" + _title["comp"] + "}}^{\mathrm{RMS}}$" 
            elif _title["mean"]:
                #r"$\langle$" + _title["param"] + r"$\rangle$" + r"$_{\mathrm{" + _title["comp"] + "}}^{ }$" 
                ttl = r"$\langle$" + _title["param"] + r"$_{\mathrm{" + _title["comp"] + "}}^{ }$" + r"$\rangle$"  
            elif _title["diff"]:
                ttl = r"$\Delta$ " + _title["param"] + r"$_{\mathrm{" + _title["comp"] + "}}^{" + _title["diff_label"] + "}$" 
            else:
                ttl =  _title["param"] + r"$_{\mathrm{" + _title["comp"] + "}}^{ }$" 
            try:
                ttl = _title["custom"]
            except:
                pass

            # Left signal label
            lttl = r"$" + _title["sig"] +"$"
            if lttl == "$I$":
                lttl = "$T$"
            elif lttl == "$QU$":
                lttl= "$P$"

            # Tick bug fix
            mn = ticks[0]
            mx = ticks[-1]
            md = None
            if not mid and len(ticks)>2:
                if ticks[0]<ticks[1]  and ticks[-2]<ticks[-1]:
                    md = ticks[1:-1]
                else:
                    ticks.pop(1)


            # Unit
            unt = _title["unit"]
        else:
            ttl = ""
            lttl = ""
            unt = ""
            md = None
            ticks = [False, False]
            cmp = "planck"
            lgscale = False


        # If min and max have been specified, set.
        if rng == "auto" and not auto:
            click.echo(click.style("Setting range from 97.5th percentile of data",fg="yellow"))
            mn, mx = get_ticks(m, 97.5)
        elif rng == "minmax":
            click.echo(click.style("Setting range from min to max of data",fg="yellow"))
            mn = np.min(m)
            mx = np.max(m)
        else:
            try:
                if float(rng)>0.0:
                    mn = -float(rng)
                    mx = float(rng)
                    ticks = [False, 0.0, False]
            except:
                pass

        if min is False:
            min = mn
        else:
            min = float(min)

        if max is False:
            max = mx
        else:
            max = float(max)   

        ticks[0] = min
        ticks[-1] = max
        if mid:
            ticks = [min, *mid, max]
        elif md:
            ticks = [min, *md, max] 
        ticks = [float(i) for i in ticks]
        ##########################
        #### Plotting Params #####
        ##########################

        # Upper right title
        if not title:
            title = ttl

        # Upper left title
        if not ltitle:
            ltitle = lttl

        # Unit under colorbar
        if not unit:
            unit = unt

        # Image size -  ratio is always 1/2
        xsize = 2000
        ysize = int(xsize / 2.0)

        ticklabels = ticks
        #######################
        ####   logscale   #####
        #######################
        # Some maps turns on logscale automatically
        # -logscale command overwrites this
        if logscale == None:
            logscale = lgscale

        if logscale:
            click.echo(click.style("Applying semi-logscale", fg="yellow", blink=True, bold=True))
            starttime = time.time()
            linthresh=1
            m = symlog(m,linthresh)

            ticks = []
            for i in ticklabels:
                ticks.append(symlog(i,linthresh))

            m = np.maximum(np.minimum(m, ticks[-1]), ticks[0])

            click.echo("Logscale", (time.time() - starttime),) if verbose else None

        ######################
        #### COLOR SETUP #####
        ######################
        # Chose colormap manually
        if cmap == None:
            # If not defined autoset or goto planck
            cmap = cmp
        if cmap == "planck":
            from pathlib import Path
            if False: #logscale:
                cmap = Path(__file__).parent / "planck_cmap_logscale.dat"
            else:
                cmap = Path(__file__).parent / "planck_cmap.dat"
            cmap = col.ListedColormap(np.loadtxt(cmap) / 255.0, "planck")
        elif cmap.startswith("q-"):
            import plotly.colors as pcol
            _, clab, *numvals = cmap.split("-")
            colors = getattr(pcol.qualitative, clab)
            if clab=="Plotly":
                #colors.insert(3,colors.pop(-1))
                colors.insert(0,colors.pop(-1))
                colors.insert(3,colors.pop(2))
            try:
                cmap = col.ListedColormap(colors[:int(numvals[0])], f'{clab}-{numvals[0]}')
                click.echo(click.style("Using qualitative colormap:", fg="yellow") + f" {clab} up to {numvals[0]}")
            except:
                cmap = col.ListedColormap(colors,clab)
                click.echo(click.style("Using qualitative colormap:", fg="yellow") + f" {clab}")
        elif cmap.startswith("black2"):
            cmap = col.LinearSegmentedColormap.from_list(cmap,cmap.split("2"))
        else:
            try:
                import cmasher
                cmap = eval(f"cmasher.{cmap}")
            except:
                cmap = plt.get_cmap(cmap)

        click.echo(click.style("Colormap:", fg="green") + f" {cmap.name}")
        #######################
        ####  Projection? #####
        #######################
        theta = np.linspace(np.pi, 0, ysize)
        phi = np.linspace(-np.pi, np.pi, xsize)
        longitude = np.radians(np.linspace(-180, 180, xsize))
        latitude = np.radians(np.linspace(-90, 90, ysize))

        # project the map to a rectangular matrix xsize x ysize
        PHI, THETA = np.meshgrid(phi, theta)
        grid_pix = hp.ang2pix(nside, THETA, PHI)

        ######################
        ######## Mask ########
        ######################
        if mask:
            click.echo(click.style(f"Masking using {mask}", fg="yellow"))
            masked = True

            # Apply mask
            hp.ma(m)
            mask_field = polt-3 if polt>2 else polt
            m.mask = np.logical_not(hp.read_map(mask, field=mask_field, verbose=False, dtype=None))

            # Don't know what this does, from paperplots by Zonca.
            grid_mask = m.mask[grid_pix]
            grid_map = np.ma.MaskedArray(m[grid_pix], grid_mask)

            if mfill:
                cmap.set_bad(mfill)  # color of missing pixels
                # cmap.set_under("white") # color of background, necessary if you want to use
                # using directly matplotlib instead of mollview has higher quality output
        else:
            grid_map = m[grid_pix]

        ######################
        #### Formatting ######
        ######################
        from matplotlib.projections.geo import GeoAxes

        class ThetaFormatterShiftPi(GeoAxes.ThetaFormatter):
            """Shifts labelling by pi
            Shifts labelling from -180,180 to 0-360"""

            def __call__(self, x, pos=None):
                if x != 0:
                    x *= -1
                if x < 0:
                    x += 2 * np.pi
                return GeoAxes.ThetaFormatter.__call__(self, x, pos)

        # Format tick labels
        click.echo(click.style("Ticks: ", fg="green") + f"{ticklabels}")
        ticklabels = [fmt(i, 1) for i in ticklabels]
        click.echo(click.style("Unit: ", fg="green") + f"{unit}")
        click.echo(click.style("Title: ", fg="green") + f"{title}")


        sizes = get_sizes(size)
        for width in sizes:
            # Size of plot
            click.echo(click.style("Size: ", fg="green") + str(width))
            height = width / 2.0
            height *= 1.275 if colorbar else 1 # Make sure text doesnt change with colorbar

            ################
            ##### font #####
            ################
            fontsize = 10

            fig = plt.figure(figsize=(cm2inch(width), cm2inch(height),),)
            ax = fig.add_subplot(111, projection="mollweide")

            # rasterized makes the map bitmap while the labels remain vectorial
            # flip longitude to the astro convention
            image = plt.pcolormesh(longitude[::-1], latitude, grid_map, vmin=ticks[0], vmax=ticks[-1], rasterized=True, cmap=cmap, shading='auto',)
            # graticule
            ax.set_longitude_grid(60)
            ax.xaxis.set_major_formatter(ThetaFormatterShiftPi(60))

            if width < 10:
                ax.set_latitude_grid(45)
                ax.set_longitude_grid_ends(90)
            
            ################
            ### COLORBAR ###
            ################
            if colorbar:
                # colorbar
                from matplotlib.ticker import FuncFormatter, LogLocator
                cb = fig.colorbar(image, orientation="horizontal", shrink=0.4, pad=0.08, ticks=ticks, format=FuncFormatter(fmt),)

                cb.ax.set_xticklabels(ticklabels)
                cb.ax.xaxis.set_label_text(unit)
                cb.ax.xaxis.label.set_size(fontsize)
                if logscale:
                    #if f == 0:
                    #    linticks = np.array([])
                    #else:
                    linticks = np.linspace(-1, 1, 3)*linthresh
                    logmin = np.round(ticks[0])
                    logmax = np.round(ticks[-1])

                    logticks_min = -10**np.arange(0, abs(logmin)+1)
                    logticks_max = 10**np.arange(0, logmax+1)
                    ticks_ = np.unique(np.concatenate((logticks_min, linticks, logticks_max)))
                    #cb.set_ticks(np.concatenate((ticks,symlog(ticks_))), []) # Set major ticks

                    logticks = symlog(ticks_, linthresh)
                    logticks = [x for x in logticks if x not in ticks]
                    cb.set_ticks(np.concatenate((ticks,logticks ))) # Set major ticks
                    cb.ax.set_xticklabels(ticklabels + ['']*len(logticks))

                    minorticks = np.linspace(-linthresh, linthresh, 5)
                    minorticks2 = np.arange(2,10)*linthresh

                    for i in range(len(logticks_min)):
                        minorticks = np.concatenate((-10**i*minorticks2,minorticks))
                    for i in range(len(logticks_max)):
                        minorticks = np.concatenate((minorticks, 10**i*minorticks2))

                    minorticks = symlog(minorticks, linthresh)
                    minorticks = minorticks[ (minorticks >= ticks[0]) & ( minorticks<= ticks[-1]) ] 
                    cb.ax.xaxis.set_ticks(minorticks, minor=True)

                

                cb.ax.tick_params(which="both", axis="x", direction="in", labelsize=fontsize,)
                cb.ax.xaxis.labelpad = 4  # -11
                # workaround for issue with viewers, see colorbar docstring
                cb.solids.set_edgecolor("face")

            # remove longitude tick labels
            ax.xaxis.set_ticklabels([])
            # remove horizontal grid
            ax.xaxis.set_ticks([])
            ax.yaxis.set_ticklabels([])
            ax.yaxis.set_ticks([])
            plt.grid(True)

            ###################
            ## RIGHT TITLE ####
            ###################
            plt.text(4.5, 1.1, r"%s" % title, ha="center", va="center", fontsize=labelsize,)

            ##################
            ## LEFT TITLE ####
            ##################
            plt.text(-4.5, 1.1, r"%s" % ltitle, ha="center", va="center", fontsize=labelsize,)

            ##############
            #### SAVE ####
            ##############
            plt.tight_layout()
            filetype = "png" if png else "pdf"
            # Turn on transparency unless told otherwise
            tp = False if white_background else True  

            ##############
            ## filename ##
            ##############
            outfile = outfile.replace("_IQU_", "_")
            outfile = outfile.replace("_I_", "_")

            filename = []
            filename.append(f"{str(int(fwhm))}arcmin") if float(fwhm) > 0 else None
            filename.append("cb") if colorbar else None
            filename.append("masked") if masked else None
            filename.append("nodip") if remove_dipole else None
            filename.append("dark") if darkmode else None
            filename.append(f"c-{cmap.name}")

            nside_tag = "_n" + str(int(nside))
            if nside_tag in outfile:
                outfile = outfile.replace(nside_tag, "")

            fn = outfile + f"_{signal_label}_w{str(int(width))}" + nside_tag

            for i in filename:
                fn += f"_{i}"
            fn += f".{filetype}"

            starttime = time.time()
            if outdir:
                fn = outdir + "/" + os.path.split(fn)[-1]

            click.echo(click.style("Output:", fg="green") + f" {fn}")
            plt.savefig(fn, bbox_inches="tight", pad_inches=0.02, transparent=tp, format=filetype,dpi=dpi)
            click.echo("Savefig", (time.time() - starttime),) if verbose else None

            plt.close()
            click.echo("Totaltime:", (time.time() - totaltime),) if verbose else None

        min = tempmin
        max = tempmax
        mid = tempmid
        mn = mx = md = None
        title = temptitle
        ltitle = temptitle
        unit = tempunit
        logscale = templogscale
        cmap = tempcmap
コード例 #10
0
ファイル: test_dipole.py プロジェクト: dhanson/qcinv
#!/usr/bin/env python

import healpy as hp
import numpy as np

nside = 16
xyz   = hp.pix2vec(nside, np.arange(0, 12*nside**2))

c, [dx, dy, dz] = hp.fit_dipole(np.ones(12*nside**2))
print 'c' + (' dipole map c, [dx, dy, dz] = %+2.2e, [%+2.2e, %+2.2e, %+2.2e]' % (c, dx, dy, dz))
for i, f in zip( (0, 1, 2), ('x', 'y', 'z') ):
    c, [dx, dy, dz] = hp.fit_dipole(xyz[i])
    print f + (' dipole map c, [dx, dy, dz] = %+2.2e, [%+2.2e, %+2.2e, %+2.2e]' % (c, dx, dy, dz))

alm    = np.zeros(3, dtype=np.complex)
alm[0] = np.random.standard_normal(1)[0]
alm[1] = np.random.standard_normal(1)[0]
alm[2] = np.random.standard_normal(1)[0] + np.random.standard_normal(1)[0]*1.j

tmap   = hp.alm2map(alm, nside)

c, [dx, dy, dz] = hp.fit_dipole(tmap)

alm_c  = +alm[0].real / np.sqrt(4.*np.pi)
alm_dz = +alm[1].real / np.sqrt(4.*np.pi/3.)
alm_dx = -alm[2].real / np.sqrt(2.*np.pi/3.)
alm_dy = +alm[2].imag / np.sqrt(2.*np.pi/3.)

print '    c = ',     c, '     dx = ',     dx, '     dy = ',     dy, '     dz = ',     dz
print 'alm_c = ', alm_c, ' alm_dx = ', alm_dx, ' alm_dy = ', alm_dy, ' alm_dz = ', alm_dz
コード例 #11
0
def smooth_combine(maps_and_weights, variance_maps_and_weights=None, fwhm=np.radians(2.0), degraded_nside=32, spectra=False, smooth_mask=False, spectra_mask=False, base_filename="out", root_folder=".", metadata={}, chi2=False):
    """Combine, smooth, take-spectra, write metadata

    The maps (I or IQU) are first combined with their own weights, then smoothed and degraded.
    This function writes a combined smoothed and degraded map, a spectra 1 or 6 components (not degraded) and a json file with metadata
    
    Parameters
    ----------
    maps_and_weights : list of tuples
        [(map1_array, map1_weight), (map2_array, map2_weight), ...]
        each tuple contains a I or IQU map to be combined with its own weight to give the final map
    variance_maps_and_weights : list of tuples
        same as maps_and_weights but containing variances
    fwhm : double
        smoothing gaussian beam width in radians
    degraded_nside : integer
        nside of the output map
    spectra : bool
        whether to compute and write angular power spectra of the combined map
    smooth_mask, spectra_mask : bool array
        masks for smoothing and spectra, same nside of input maps, masks shoud be true *inside* the masked region. spectra are masked with both masks. Typically smooth_mask should be a point source mask, while spectra_mask a galaxy plane mask.
    base_filename : string
        base filename of the output files
    root_folder : string
        root path of the output files
    metadata : dict
        initial state of the metadata to be written to the json files

    Returns
    -------
    None : all outputs are written to fits files
    """

    log.debug("smooth_combine")
    # check if I or IQU
    is_IQU = len(maps_and_weights[0][0]) == 3
    if not is_IQU:
        assert hp.isnpixok(len(maps_and_weights[0][0])), "Input maps must have either 1 or 3 components"

    combined_map = combine_maps(maps_and_weights)
    for m in combined_map:
        m.mask |= smooth_mask
    if not variance_maps_and_weights is None:
        combined_variance_map = combine_maps(variance_maps_and_weights)
        for m in combined_variance_map:
            m.mask |= smooth_mask

    monopole_I, dipole_I = hp.fit_dipole(combined_map[0], gal_cut=30)
    # remove monopole, only I
    combined_map[0] -= monopole_I

    if spectra:
        # save original masks
        orig_mask = [m.mask.copy() for m in combined_map] 

        # spectra
        log.debug("Anafast")
        for m in combined_map:
            m.mask |= spectra_mask
        # dividing by two in order to recover the same noise as the average map (M1 - M2)/2
        cl = hp.anafast([m/2. for m in combined_map])
        # sky fraction
        sky_frac = (~combined_map[0].mask).sum()/float(len(combined_map[0]))

        if is_IQU:
            for cl_comp in cl:
                cl_comp /= sky_frac
        else:
            cl /= sky_frac

        # write spectra
        log.debug("Write cl: " + base_filename + "_cl.fits")
        try:
            hp.write_cl(os.path.join(root_folder, base_filename + "_cl.fits"), cl)
        except exceptions.NotImplementedError:
            log.error("Write IQU Cls to fits requires more recent version of healpy")
        del cl

        if not variance_maps_and_weights is None:
            # expected cl from white noise
            # /4. to have same normalization of cl
            metadata["whitenoise_cl"] = utils.get_whitenoise_cl(combined_variance_map[0]/4., mask=combined_map[0].mask) / sky_frac
            if is_IQU:
                # /2. is the mean, /4. is the half difference in power
                metadata["whitenoise_cl_P"] = utils.get_whitenoise_cl((combined_variance_map[1] + combined_variance_map[2])/2./4., mask=combined_map[1].mask | combined_map[2].mask) / sky_frac 

        # restore masks
        for m, mask in zip(combined_map, orig_mask):
            m.mask = mask

    # smooth
    log.debug("Smooth")

    smoothed_map = hp.smoothing(combined_map, fwhm=fwhm)

    if not variance_maps_and_weights is None:
        log.debug("Smooth Variance")
        if is_IQU:
            smoothed_variance_map = [utils.smooth_variance_map(var, fwhm=fwhm) for var in combined_variance_map]
            for comp,m,var in zip("IQU", smoothed_map, smoothed_variance_map):
                 metadata["map_chi2_%s" % comp] = np.mean(m**2 / var) 
            for comp,m,var in zip("IQU", combined_map, combined_variance_map):
                 metadata["map_unsm_chi2_%s" % comp] = np.mean(m**2 / var) 
        else:
            smoothed_variance_map = utils.smooth_variance_map(combined_variance_map[0], fwhm=fwhm)
            metadata["map_chi2"] = np.mean(smoothed_map**2 / smoothed_variance_map) 
            metadata["map_unsm_chi2"] = np.mean(combined_map[0]**2 / combined_variance_map[0]) 

        del smoothed_variance_map
    # removed downgrade of variance
    # smoothed_variance_map = hp.ud_grade(smoothed_variance_map, degraded_nside, power=2)

    # fits
    log.info("Write fits map: " + base_filename + "_map.fits")
    smoothed_map = hp.ud_grade(smoothed_map, degraded_nside)
    hp.write_map(os.path.join(root_folder, base_filename + "_map.fits"), smoothed_map)

    # metadata
    metadata["base_file_name"] = base_filename
    metadata["file_name"] = base_filename + "_cl.fits"
    metadata["file_type"] += "_cl"
    metadata["removed_monopole_I"] = monopole_I
    metadata["dipole_I"] = tuple(dipole_I)

    if spectra:
        metadata["sky_fraction"] = sky_frac
        with open(os.path.join(root_folder, base_filename + "_cl.json"), 'w') as f:
            json.dump(metadata, f, indent=4)

    metadata["file_name"] = base_filename + "_map.fits"
    metadata["file_type"] = metadata["file_type"].replace("_cl","_map")

    metadata["smooth_fwhm_deg"] = "%.2f" % np.degrees(fwhm)
    metadata["out_nside"] = degraded_nside
    if is_IQU:
        for comp,m in zip("IQU", smoothed_map):
             metadata["map_p2p_%s" % comp] = m.ptp()
             metadata["map_std_%s" % comp] = m.std()
    else:
        metadata["map_p2p_I"] = smoothed_map.ptp()
        metadata["map_std_I"] = smoothed_map.std()

    with open(os.path.join(root_folder, base_filename + "_map.json"), 'w') as f:
        json.dump(metadata, f, indent=4)