Exemple #1
0
def create_cmasher_tableau_properties_file(cmap_range=(0.15,0.85)):
	"""
    Create Tableau parameters.tps file that contains colormaps from the python package CMasher
    
    Parameters:
    ==========
    colormap_range: input two float numbers in range (0, 1)
    
    Returns:
    =======
    Parameters.tps -- Tableau preferences file with CMasher's colormaps
    """
    # Get colormaps
	cmr.cm.cmap_d.keys()

	# Get type of the colormaps
	cmr.cm.cmap_cd.keys()

	# There are only sequential and diverging colormaps
	# We obtain names of colormaps using only those that do not end with '_r' since they are the reversed version of each colormap
	sequential_colormap = [y for y in cmr.cm.cmap_cd['sequential'] if not y.endswith('_r')]
	diverging_colormap = [y for y in cmr.cm.cmap_cd['diverging'] if not y.endswith('_r')]

	# Get the HEXZ values of each sequential colormaps 
	# Export them in range of: 0.15 to 0.85 -> you can export the full range if you prefer.
	all_sequential_maps_hex = []
	for colormap in sequential_colormap:
		cmp = cmr.take_cmap_colors('cmr.{}'.format(colormap), None, cmap_range=cmap_range, return_fmt='hex')
		all_sequential_maps_hex.append(cmp)

    # Get the hex values of the diverging colormaps; in range 0.15 to 0.85
	all_diverging_maps_hex = []
	for colormap in diverging_colormap:
		cmp = cmr.take_cmap_colors('cmr.{}'.format(colormap), None, cmap_range=cmap_range, return_fmt='hex')
		all_diverging_maps_hex.append(cmp)

	with open("Preferences.tps", 'w') as f:

		print("<?xml version='1.0'?>", file=f)
		print("<workbook>", file=f)
		print("    <preferences>", file=f)

	    # Get all the sequential colormaps in the format that is required in Tableau
		for i, hexes in enumerate(all_sequential_maps_hex):
			print('    <color-palette name='+'"'+'{}'.format(sequential_colormap[i])+'" ' +'type="ordered-sequential">', file=f)
			for j, col in enumerate(hexes):
				print('        <color>'+'{}'.format(hexes[j])+'</color>', file=f)
			print('    </color-palette>', file=f)

	 	# Get all the diverging colormaps in the format that is required in Tableau
		for i, hexes in enumerate(all_diverging_maps_hex):
			print('<color-palette name='+'"'+'{}'.format(diverging_colormap[i])+'" ' +'type="ordered-diverging">', file=f)
			for j, col in enumerate(hexes):
				print('        <color>'+'{}'.format(hexes[j])+'</color>', file=f)
			print('    </color-palette>', file=f)

		print("    </preferences>", file=f)
		print("</workbook>", file=f)
Exemple #2
0
    def calc_mesh(n, vcode):
        def fmt_code(a):
            return np.array(a, dtype=np.float32)

        _lap = timeit.default_timer()

        vertexes, textures = SpherHarm.calc_vertex_texture(n, fmt_code(vcode))
        normals = SpherHarm.calc_normals(vertexes)
        colors = cmr.take_cmap_colors('cmr.rainforest', n)

        return timeit.default_timer(
        ) - _lap, vertexes, normals, colors, textures
Exemple #3
0
def cli_cmap_colors():
    # Import cmap packages
    import_cmap_pkgs()

    # Obtain the colors
    colors = cmr.take_cmap_colors(get_cmap(ARGS.cmap), ARGS.ncolors,
                                  cmap_range=ARGS.cmap_range,
                                  return_fmt=ARGS.return_fmt)

    # Print the colors line-by-line
    if ARGS.return_fmt in ('float', 'norm'):
        np.savetxt(sys.stdout, colors, '%.8f')
    elif ARGS.return_fmt in ('int', '8bit'):
        np.savetxt(sys.stdout, colors, '%i')
    else:
        np.savetxt(sys.stdout, colors, '%s')
def plt_modelsonly(
    save_dir,
    gleam_target,
    fit_freq,
    src_flux,
    err_src_flux,
    yvals,
    logz,
    epoch_nm,
    ext="pdf",
    colors=cmr.take_cmap_colors(
        "cmr.cosmic", 8, cmap_range=(0.15, 0.8), return_fmt="hex"
    ),
):

    model_nms = [
        "SSA",
        "FFA",
        "inFFA",
        "SSAb",
        "FFAb",
        "inFFAb",
    ]
    target = gleam_target.strip("GLEAM ")[0:7]
    f = CF.sed_fig()
    f.plot_spectrum(
        fit_freq,
        src_flux,
        err_src_flux,
        marker="o",
        marker_color="k",
        s=5,
    )
    for i in range((len(yvals))):
        f.display_model(
            np.linspace(0.01, 25, num=10000),
            yvals[i],
            colors[i],
            lw=0.5,
            label=f"{model_nms[i]}, logz: {logz[i]:.2f}",
        )
    f.legend(loc="lower left", ncol=1)
    f.format(xunit="GHz")
    f.title(f"{gleam_target}: {epoch_nm} Models")
    f.save(f"{save_dir}{target}_{epoch_nm}_models", ext=ext)
    plt.close()
    plt.clf()
def change_style(geojson,legend, style):
    cmap = cm.get_cmap('viridis', 500)    # PiYG
    stop=1
    start=0
    lista=np.linspace(start, stop, num=500)
    colors = cmr.take_cmap_colors(style, 500, return_fmt='hex')
    print(lista)
    print(colors)
    with open('static/geojson/'+geojson+'.geojson', 'r') as j:
        json_data = json.load(j)
        print(json_data.keys())
        for n in range(0,len(json_data['features'])):
            value=int(json_data['features'][n]['properties']['Riesgo']/0.002004008016032064 )
            #print(json_data['features'][n]['properties']['Riesgo'])
            #print(lista[value])
            #print(json_data['features'][n]['properties']['style']['fillColor'])
            json_data['features'][n]['properties']['style']['fillColor']=colors[value]
            #print(json_data['features'][n]['properties']['style']['fillColor'])
        with open('static/geojson/'+geojson.split('_l')[0]+'_'+legend+'.geojson', 'w') as file:
            json.dump(json_data, file)
def plt_mwa_sed(
    data_dir,
    save_dir,
    gleam_target,
    model,
    ext="pdf",
    epochs=[
        "2013",
        "2014",
        "2020-01",
        "2020-03",
        "2020-04",
        "2020-05",
        "2020-07",
        "2020-09",
    ],
    colors=cmr.take_cmap_colors(
        "cmr.gothic", 8, cmap_range=(0.15, 0.8), return_fmt="hex"
    ),
    epoch_nms=["2013", "2014", "Jan20", "Mar20", "Apr20", "May20", "Jul20", "Sept20"],
):
    target = gleam_target.strip("GLEAM ")[0:7]
    frequency = np.array(
        [
            0.076,
            0.084,
            0.092,
            0.099,
            0.107,
            0.115,
            0.122,
            0.130,
            0.143,
            0.151,
            0.158,
            0.166,
            0.174,
            0.181,
            0.189,
            0.197,
            0.204,
            0.212,
            0.220,
            0.227,
        ]
    )

    mwa_fluxes, err_mwa_fluxes = fitfuncts.read_mwa_fluxes(
        "/data/MWA", target, gleam_target, epochs
    )
    apr_normfact = np.nanmax(mwa_fluxes[4])
    may_normfact = np.nanmedian(mwa_fluxes[4][10:20] - mwa_fluxes[5][10:20])
    jul_normfact = np.nanmedian(mwa_fluxes[4][10:20] - mwa_fluxes[6][10:20])
    oct_normfact = np.nanmedian(mwa_fluxes[4][10:20] - mwa_fluxes[7][10:20])
    yvals, nu_p, err_nu_p, alpha, err_alpha = calc_modelnparams(data_dir, target, model)
    if target == "J223933":
        ylabel = "Relative Flux Density"
        yunit = ""
        yvals = yvals[4:8]
        colors = colors[4:8]
        epochnms = epoch_nms[4:8]
        mwaflux_2020 = mwa_fluxes[4:8]
        errmwaflux_2020 = err_mwa_fluxes[4:8]
        errmwaflux_2020 = errmwaflux_2020 / apr_normfact
        mwaflux_2020[0] = mwaflux_2020[0] / apr_normfact
        mwaflux_2020[1] = (mwaflux_2020[1] + may_normfact) / apr_normfact
        mwaflux_2020[2] = (mwaflux_2020[2] + jul_normfact) / apr_normfact
        mwaflux_2020[3] = (mwaflux_2020[3] + oct_normfact) / apr_normfact
        yvals[0] = yvals[0] / apr_normfact
        yvals[1] = (yvals[1] + may_normfact) / apr_normfact
        yvals[2] = (yvals[2] + jul_normfact) / apr_normfact
        yvals[3] = (yvals[3] + oct_normfact) / apr_normfact
        yvals_2020 = yvals
    else:
        ylabel = "Flux Density"
        yunit = "Jy"
        yvals_2020 = yvals
        epochnms = epoch_nms
        mwaflux_2020 = mwa_fluxes
        errmwaflux_2020 = err_mwa_fluxes
    f = CF.sed_fig()
    for i in range(len(epochnms)):
        if epochnms[i] in ["2013", "2014", "Apr20", "May20", "Jul20", "Sept20"]:
            f.plot_spectrum(
                frequency,
                mwaflux_2020[i],
                errmwaflux_2020[i],
                marker="o",
                label=epochnms[i],
                marker_color=colors[i],
                s=5,
            )
            f.display_model(
                np.linspace(0.01, 25, num=10000), yvals_2020[i], colors[i], lw=1
            )
    f.legend(loc="lower right")#, fontsize=20)
    # f.format(xunit="GHz",xlabelfontsize=25, ylabelfontsize=25, ticklabelfontsize=20,majorticklength=7.5, minorticklength=6, tickwidth=1, ylabel=ylabel, yunit=yunit)
    f.format(xunit="GHz", ylabel=ylabel, yunit=yunit)
    f.title(f"{gleam_target}")#, fontsize=40)
    f.save(f"{save_dir}{target}_mwa", ext=ext)
    plt.clf()
    plt.close()
    return
def plt_peakftime(
    save_dir,
    nu_p,
    err_nu_p,
    plot_title,
    ext="pdf",
    colors=cmr.take_cmap_colors(
        "cmr.gothic", 8, cmap_range=(0.15, 0.8), return_fmt="hex"
    ),
):
    figsize = (3.5, 1.5)
    # fig = plt.figure(1, figsize=figsize, facecolor="white")
    fig = plt.figure(figsize=figsize)
    gs = fig.add_gridspec(1, 2, wspace=0.05, width_ratios=[1, 3])
    ax = gs.subplots()
    fig.suptitle(plot_title, fontsize=8)
    ax[0].set_ylabel(r"$\nu_p$ (GHz)", fontsize=8)
    # ax[1].set_xlabel(r"Date", fontsize=8)
    fig.text(
        0.5, -0.06, f"Date", ha="center", fontsize=8
    )
    ax[0].tick_params(
        axis="both", which="major", direction="in", length=2.5, width=0.5, pad=5
    )
    ax[0].tick_params(axis="both", which="minor", direction="in", length=2, width=0.5)
    ax[0].tick_params(axis="both", which="both", labelsize="8", right=True, top=True)
    ax[1].tick_params(
        axis="both", which="major", direction="in", length=2.5, width=0.5, pad=5
    )
    ax[1].tick_params(axis="both", which="minor", direction="in", length=2, width=0.5)
    ax[1].tick_params(axis="both", which="both", labelsize="8", right=True, top=True)
    ax[0].spines["right"].set_visible(False)
    ax[1].spines["left"].set_visible(False)
    ax[0].yaxis.set_ticks_position("left")
    ax[1].yaxis.set_ticks_position("right")
    ax[1].yaxis.set_ticklabels([])
    d = 1
    kwargs = dict(
        marker=[(-1, -d), (1, d)],
        markersize=3,
        linestyle="none",
        color="k",
        mec="k",
        mew=1,
        clip_on=False,
    )
    ax[0].plot([1, 1], [0, 1], transform=ax[0].transAxes, **kwargs)
    ax[1].plot([0, 0], [0, 1], transform=ax[1].transAxes, **kwargs)

    months = [-5, -4, 1, 3, 4, 5, 7, 9]
    for i in range(len(months)):
        ax[0].errorbar(
            months[i],
            nu_p[i],
            yerr=np.array([[err_nu_p[0, i], err_nu_p[1, i]]]).T,
            fmt="o",
            color=colors[i],
            capsize=1,
            markersize=2,
            elinewidth=0.5,
        )
        ax[1].errorbar(
            months[i],
            nu_p[i],
            yerr=np.array([[err_nu_p[0, i], err_nu_p[1, i]]]).T,
            fmt="o",
            color=colors[i],
            capsize=1,
            markersize=2,
            elinewidth=0.5,
        )
    # for axis in ["top", "bottom", "left", "right"]:
    #     ax[0].spines[axis].set_linewidth(2)
    #     ax[1].spines[axis].set_linewidth(2)
    ax[0].set_xticks([-5, -4, 4, 5, 7, 9])
    ax[1].set_xticks([-5, -4, 4, 5, 7, 9])
    ax[0].set_xticklabels(["'13", "'14", "Apr20", "May20", "Jul20", "Sept20"])
    ax[1].set_xticklabels(["'13", "'14", "Apr20", "May20", "Jul20", "Sept20"])
    ax[0].set_xlim([-6, -3])
    ax[1].set_xlim([3.5, 9.5])
    # plt.tight_layout()

    plt.savefig(f"{save_dir}_peakfreqvstime.{ext}", overwrite=True, bbox_inches='tight')
    plt.clf()
    plt.close()
    return
def plt_sed(
    data_dir,
    save_dir,
    gleam_target,
    src_flux,
    err_src_flux,
    extra_surveys,
    yvals,
    ext="pdf",
    colors=cmr.take_cmap_colors(
        "cmr.gothic", 8, cmap_range=(0.15, 0.8), return_fmt="hex"
    ),
    epochnms=[
        "2013",
        "2014",
        "Jan20",
        "Mar20",
        "Apr20",
        "May20",
        "Jul20",
        "Sept20",
        "2020",
    ],
    frequency=np.array(
        [
            0.076,
            0.084,
            0.092,
            0.099,
            0.107,
            0.115,
            0.122,
            0.130,
            0.143,
            0.151,
            0.158,
            0.166,
            0.174,
            0.181,
            0.189,
            0.197,
            0.204,
            0.212,
            0.220,
            0.227,
            1.33,
            1.407,
            1.638,
            1.869,
            2.1,
            2.331,
            2.562,
            2.793,
            4.71,
            5.090,
            5.500,
            5.910,
            6.320,
            8.732,
            9.245,
            9.758,
            10.269,
        ]
    ),
):
    extra_frequencies = [
        0.150,
        0.408,
        0.843,
        1.400,
        0.074,
        20,
        8.6,
        4.8,
        0.8875,
    ]
    target = gleam_target.strip("GLEAM ")[0:7]
    f = CF.sed_fig()
    extra_markers = ["X", "s", "*", "p", "D", ">", "<", "^", "1"]
    print(np.shape(yvals))
    print(np.shape(src_flux))
    for i in range((len(yvals))):
        f.display_model(np.linspace(0.01, 25, num=10000), yvals[i], colors[i])
    for i in range(len(extra_surveys)):
        if extra_surveys[i] == 0.0:
            extra_surveys[i] = np.nan
        f.plot_point(
            extra_frequencies[i],
            extra_surveys[i],
            marker=extra_markers[i],
            marker_color="k",
            s=10,
            alpha=0.5,
        )
    for i in range((8)):
        f.plot_spectrum(
            frequency,
            src_flux[i],
            err_src_flux[i],
            marker="o",
            label=epochnms[i],
            marker_color=colors[i],
            s=5,
        )

    # f.plot_spectrum(frequency, src_flux[-1], err_src_flux[-1], marker="X", label="2020", marker_color="k",s=5)
    f.legend(loc="lower center")#, fontsize=20)
    f.format(xunit="GHz")#,xlabelfontsize=25, ylabelfontsize=25, ticklabelfontsize=20,majorticklength=7.5, minorticklength=6, tickwidth=1)
    f.title(f"{gleam_target}")#, fontsize=40)
    f.save(f"{save_dir}{target}_sed", ext=ext)
    plt.close()
    plt.clf()
    return
import cmasher as cmr
import matplotlib.pyplot as plt
import math

# from casatasks import uvmodelfit
import datetime
import os

from casacore.tables import table
import fitfuncts
import CFigTools.CustomFigure as CF
import priortransfuncts

num_colors = 8
colors = cmr.take_cmap_colors(
    "cmr.gothic", num_colors, cmap_range=(0.15, 0.8), return_fmt="hex"
)
freq_cont = np.linspace(0.01, 25, num=10000)
frequency = np.array(
    [
        0.076,
        0.084,
        0.092,
        0.099,
        0.107,
        0.115,
        0.122,
        0.130,
        0.143,
        0.151,
        0.158,
    def bokeh_set_plot_properties(plot_mode, n):
        """
        Constructs a list of properties that will be assigned to a Bokeh
        figure depending whether it is in the Light or Dark Mode.

        Parameters
        ----------
        plot_mode : string; plot 'Dark Mode' or 'Light Mode'

        Returns
        -------
        p : Bokeh Figure
        colors_cmr : Colors from the colormap to be assigned to lines

        """

        p = figure(height=450, width=700)

        p.add_layout(Legend(), 'right')
        p.legend.title = '15 Best Fits and their SSE'
        p.legend.background_fill_alpha = 1
        p.legend.label_text_font_size = '11pt'
        p.xgrid.grid_line_color = None
        p.ygrid.grid_line_color = None
        p.xaxis.axis_label = f'{data_col}'
        p.yaxis.axis_label = 'Density'

        if plot_mode == 'Dark Mode':
            text_color = 'white'
            back_color = 'black'
            legend_color = 'yellow'

            # It will get n colors from cmasher rainforest map
            # if n>15, it will take 15; otherwise n will be the
            # lengthe of the chosed distributions (n defined line 685)
            colors_cmr = cmr.take_cmap_colors('cmr.rainforest_r',
                                              n,
                                              cmap_range=(0.1, 0.7),
                                              return_fmt='hex')

        if plot_mode == 'Light Mode':
            text_color = 'black'
            back_color = 'white'
            legend_color = 'blue'

            colors_cmr = cmr.take_cmap_colors('cmr.rainforest',
                                              n,
                                              cmap_range=(0.2, 0.9),
                                              return_fmt='hex')

        p.legend.title_text_color = text_color
        p.yaxis.major_label_text_color = text_color
        p.xaxis.axis_label_text_color = text_color
        p.xaxis.major_label_text_color = text_color
        p.yaxis.axis_label_text_color = text_color
        p.xaxis.major_tick_line_color = text_color
        p.yaxis.major_tick_line_color = text_color
        p.xaxis.minor_tick_line_color = text_color
        p.yaxis.minor_tick_line_color = text_color
        p.xaxis.axis_line_color = text_color
        p.yaxis.axis_line_color = text_color

        p.border_fill_color = back_color
        p.background_fill_color = back_color
        p.legend.background_fill_color = back_color
        p.legend.label_text_color = legend_color
        p.title.text_color = legend_color
        p.outline_line_color = back_color

        return p, colors_cmr
# Importing required Libraries
import geopandas as gpd
import json
import pandas as pd

import numpy as np
import matplotlib.pyplot as plt
from pylab import *
import cmasher as cmr

cmap = cm.get_cmap('viridis', 500)    # PiYG
stop=1
start=0
lista=np.linspace(start, stop, num=500)
colors = cmr.take_cmap_colors('viridis', 500, return_fmt='hex')
print(lista)
print(colors)
def change_style(geojson,legend, style):
    cmap = cm.get_cmap('viridis', 500)    # PiYG
    stop=1
    start=0
    lista=np.linspace(start, stop, num=500)
    colors = cmr.take_cmap_colors(style, 500, return_fmt='hex')
    print(lista)
    print(colors)
    with open('static/geojson/'+geojson+'.geojson', 'r') as j:
        json_data = json.load(j)
        print(json_data.keys())
        for n in range(0,len(json_data['features'])):
            value=int(json_data['features'][n]['properties']['Riesgo']/0.002004008016032064 )
Exemple #12
0
def trace_plot(samples=None, live_samples=None, likelihood=None,
               lnX=None, parameter_names=None, cmap='cmr.ocean',
               color_live='#e34a33', fig=None, hist_bins=30):
    """
    Produces a set of "trace plots" for a nested sampling run,
    showing the position of "dead" points as a function of prior mass.
    Also plots the distributions of dead points accumulated until now, and the
    distributions of live points.

    Parameters
    ----------
    samples : numpy.ndarray
        (Nsamples, Npars)-array containing the rejected points
    likelihood : numpy.ndarray
        Nsamples-array containing the log likelihood values
    lnX : numpy.ndarray
        Nsamples-array containing the "prior mass"
    parameter_names : list or tuple
        List of the nPars active parameter names
    live_samples : numpy.ndarray, optional
        (Nsamples, Npars)-array containing the present live points
    cmap : str
        Name of the colormap to be used
    color_live : str
        Colour used for the live points distributions (if those are present)
    fig : matplotlib.Figure
        If a previous figure was generated, it can be passed to this function
        for update using this argument
    hist_bins : int
        The number of bins used for the histograms

    Returns
    -------
    fig : matplotlib.Figure
        The figure produced
    """
    _, nParams = samples.shape

    nrows = nParams+1
    height = min(nrows*1.5, 11.7) # Less than A4 height

    if fig is None:
        fig, axs = plt.subplots(nrows=nrows, ncols=2,
                                gridspec_kw={'width_ratios':[3,2]},
                                figsize=(8.3, height), dpi=125)
    else:
        axs = np.array(fig.axes).reshape(nrows,2)

    norm_likelihood = likelihood
    norm_likelihood = norm_likelihood - norm_likelihood.min()
    norm_likelihood = norm_likelihood/norm_likelihood.max()

    plot_settings = {'marker': '.', 'linestyle':'none'}

    colors = cmr.take_cmap_colors(cmap, nParams+1,
                                  cmap_range=(0.1, 0.85),
                                  return_fmt='hex')

    # Works on the trace plots
    for i, ax in enumerate(axs[:,0]):
        if i==0:
            y = norm_likelihood
            ax.set_ylabel(r'$\ln\mathcal{L}$'+'\n(normaliz.)')
        else:
            y = samples[:,i-1]
            if parameter_names is not None:
                ax.set_ylabel(parameter_names[i-1])
            else:
                ax.set_ylabel(i)

        plot_settings['color'] = colors[i]
        ax.plot(-lnX, y, **plot_settings)
        ax.set_xlabel('$-\ln X$')

    # Works on the histograms
    for i, ax in enumerate(axs[:,1]):
        if i==0:
            ax.set_axis_off()
        else:
            if parameter_names is not None:
                ax.set_xlabel(parameter_names[i-1])
            else:
                ax.set_xlabel(i)
            hist, edges = np.histogram(samples[:,i-1], bins=hist_bins)

            ax.plot(edges[:-1], hist, color=colors[i], drawstyle='steps-pre',
                    label='rej.')

            if live_samples is not None:
                hist_live, edges_live = np.histogram(live_samples[:,i-1],
                                                     bins=hist_bins)

                # Makes sure everything is visible in the same histogram
                hist_live = hist_live* hist.max()/hist_live.max()

                ax.plot(edges_live[:-1], hist_live, color=color_live,
                        drawstyle='steps-pre', label='live')
            ax.legend(frameon=False)

    plt.tight_layout()
    return fig
Exemple #13
0
def plot_mwa_nearby(
    save_dir,
    target,
    cat_tar,
    ext="png",
    epochs=["2013", "2014", "2020-04", "2020-05", "2020-07", "2020-09"],
    colors=cmr.take_cmap_colors("cmr.gothic",
                                8,
                                cmap_range=(0.15, 0.8),
                                return_fmt="hex"),
    frequency=np.array([
        0.076,
        0.084,
        0.092,
        0.099,
        0.107,
        0.115,
        0.122,
        0.130,
        0.143,
        0.151,
        0.158,
        0.166,
        0.174,
        0.181,
        0.189,
        0.197,
        0.204,
        0.212,
        0.220,
        0.227,
    ]),
):

    tar = target.strip("GLEAM ")[0:7]
    fluxes, err_fluxes = read_MWA_fluxes("/data/MWA/", cat_tar, target)
    ylabel = "Flux Density"
    yunit = "Jy"
    epochnms = ["2013", "2014", "Apr20", "May20", "Jul20", "Sept20"]
    f = CF.sed_fig()
    for i in [0, 1]:
        f.plot_spectrum(
            frequency,
            fluxes[i],
            err_fluxes[i],
            marker="o",
            label=epochnms[i],
            marker_color=colors[i],
            s=5,
        )
    for i in [2, 3, 4, 5]:
        f.plot_spectrum(
            frequency,
            fluxes[i],
            err_fluxes[i],
            marker="o",
            label=epochnms[i],
            marker_color=colors[i + 2],
            s=5,
        )
    f.legend()  #loc="lower center")
    f.format(xunit="GHz", ylabel=ylabel, yunit=yunit)
    f.title(f"{target}")
    f.save(f"{save_dir}{cat_tar}_nearbysrc_{tar}", ext=ext)
    return
Exemple #14
0
def plot_detect_language2(DATAFRAME, temp_dir):
    '''
    Function to get plot dougnut chart for detect language
    '''
    # get the dataframe & prepare for plot
    lang = get_total_language(DATAFRAME)
    most_lang = lang['Language'][0]
    # Create new column to get anotate value for plot
    anotate_col = 'anotate'
    percent_format = "{0:.1f}%"
    percent_coeff = 100
    lang[anotate_col] = (lang.review / lang.review.sum())
    lang[anotate_col] = pd.Series([percent_format.format(val * percent_coeff) for val in lang[anotate_col]],
                                  index=lang.index)
    lang[anotate_col] = lang[anotate_col].str.cat(lang.Language, sep=' ')
    # define value for the label
    anotate = lang.anotate.to_list()
    data = lang.review.to_list()

    # Set parameter for plot
    cmap_type = 'cmr.sepia_r'
    color_format = 'hex'
    rcParams = 'axes.prop_cycle'
    aspect = "equal"
    cmap_n = 5

    cmap_range = (0.15, 0.85)
    width = 0.5
    angle = -40

    # Set color map using cmasher
    colors = cmr.take_cmap_colors(
        cmap_type, cmap_n, cmap_range=cmap_range, return_fmt=color_format)
    plt.rcParams[rcParams] = cycler(color=colors)

    # install font for plot
    path = 'sentiport/utils/Helvetica-Font/Helvetica-Bold.ttf'
    path1 = 'sentiport/utils/Helvetica-Font/Helvetica-Oblique.ttf'
    Helvetica_Bold = fm.FontProperties(fname=path, size=18)
    Helvetica = fm.FontProperties(fname=path1, size=15)

    # Create the plot function to generate dougnut chart
    obj, ax = plt.subplots(figsize=(9.03307, 4.7017),
                           dpi=100, subplot_kw=dict(aspect=aspect))
    wedges, texts = ax.pie(data, wedgeprops=dict(
        width=width), startangle=angle)
    bbox_props = dict(boxstyle="square,pad=0.3", fc="w", ec="k", lw=0.72)
    kw = dict(arrowprops=dict(arrowstyle="-"),
              bbox=bbox_props, zorder=0, va="center")

    for i, p in enumerate(wedges):
        ang = (p.theta2 - p.theta1) / 2. + p.theta1
        y = np.sin(np.deg2rad(ang))
        x = np.cos(np.deg2rad(ang))
        horizontalalignment = {-1: "right", 1: "left"}[int(np.sign(x))]
        connectionstyle = "angle,angleA=0,angleB={}".format(ang)
        kw["arrowprops"].update({"connectionstyle": connectionstyle})
        ax.annotate(anotate[i], xy=(x, y), xytext=(1.35 * np.sign(x), 1.4 * y),
                    horizontalalignment=horizontalalignment, **kw, fontproperties=Helvetica)

    sumstr = 'From\n' + str(lang.review.sum()) + '\nReviews'
    ax.text(0., 0., sumstr, horizontalalignment='center',
            verticalalignment='center', fontproperties=Helvetica_Bold)

    obj.savefig(f'sentiport/artifacts/{temp_dir}/fig_lang.png')

    return f'sentiport/artifacts/{temp_dir}/fig_lang.png', most_lang
Exemple #15
0
def double_contourplot(var1var2, model):

    recoverpath = dict(base='/',
                       temp='data/additional_data/temp/{}/'.format(ex_op_str))

    # load all dictionaries and strings from json file #

    json_filename = 'deterministic_overview_maps_{}_{}_dicts_strings.json'.format(
        model, var1var2)
    with open(recoverpath['base'] + recoverpath['temp'] + json_filename,
              'r') as f:
        path, domain, variable1, variable2, run, hour = json.load(f)

    # load numpy arrays #

    if variable1['load_global_field']:
        numpyarrays_filename = 'deterministic_overview_maps_{}_{}_ndarrays_outofloop.npz'.format(
            model, var1var2)

        if model == 'icon-eu-det':
            with open(path['base'] + path['temp'] + numpyarrays_filename,
                      'rb') as f:
                with np.load(f) as loadedfile:
                    clat = loadedfile['clat']
                    clon = loadedfile['clon']

        elif model == 'icon-global-det':
            if not variable1['load_global_field']:
                with open(path['base'] + path['temp'] + numpyarrays_filename,
                          'rb') as f:
                    with np.load(f) as loadedfile:
                        ll_lat = loadedfile['ll_lat']
                        ll_lon = loadedfile['ll_lon']
            elif variable2['name'] == '':
                with open(path['base'] + path['temp'] + numpyarrays_filename,
                          'rb') as f:
                    with np.load(f) as loadedfile:
                        clat = loadedfile['clat']
                        clon = loadedfile['clon']
                        vlat = loadedfile['vlat']
                        vlon = loadedfile['vlon']
            else:
                with open(path['base'] + path['temp'] + numpyarrays_filename,
                          'rb') as f:
                    with np.load(f) as loadedfile:
                        clat = loadedfile['clat']
                        clon = loadedfile['clon']
                        vlat = loadedfile['vlat']
                        vlon = loadedfile['vlon']
                        ll_lat = loadedfile['ll_lat']
                        ll_lon = loadedfile['ll_lon']

        numpyarrays_filename = 'deterministic_overview_maps_{}_{}_ndarrays_withinloop.npz'.format(
            model, var1var2)
        with open(
                recoverpath['base'] + recoverpath['temp'] +
                numpyarrays_filename, 'rb') as f:
            with np.load(f) as loadedfile:
                data_array1 = loadedfile['data_array1']
                if variable2['name'] != '':
                    data_array2 = loadedfile['data_array2']

        #print('loaded all vars')

        if domain['limits_type'] == 'radius':
            margin_deg = 20
        elif domain['limits_type'] == 'deltalatlon' or domain[
                'limits_type'] == 'angle':
            margin_deg = 20

        if model == 'icon-eu-det':
            data_array1_cut, clat_cut, clon_cut, vlat_cut, vlon_cut = data_array1, clat, clon, None, None
        elif model == 'icon-global-det':
            data_array_dims = '2d'
            [data_array1_cut], clat_cut, clon_cut, vlat_cut, vlon_cut = \
              cut_by_domain(domain, variable1['grid'], data_array_dims,
                            [data_array1], clat, clon, vlat, vlon, margin_deg)
            if variable2['name'] != '':
                [data_array2_cut], ll_lat_cut, ll_lon_cut = \
                  cut_by_domain(domain, variable2['grid'], data_array_dims,
                                [data_array2], ll_lat, ll_lon, None, None, margin_deg)
                #data_array2_cut, ll_lat_cut, ll_lon_cut = data_array2, ll_lat, ll_lon
    else:
        # if load_global_field == False
        if variable1['name'][:2] == 'pv'\
         and variable1['name'][-1:] == 'K':
            iso_theta_value = float(variable1['name'][3:6])
            data_array1_cut, clat_cut, clon_cut \
             = calc_pv_on_theta(model, domain, variable1['grid'], run, hour, iso_theta_value)
        elif variable1['name'][:5] == 'theta'\
         and variable1['name'][-3:] == 'PVU':
            iso_pv_value = float(variable1['name'][6:9])
            data_array1_cut, clat_cut, clon_cut \
             = calc_theta_on_pv(model, domain, variable1['grid'], run, hour, iso_pv_value)

    # example plot_name: icon-global-det_2020070512_prec_rate_mslp_europe_000h.png
    plot_name = '{}_{:4d}{:02d}{:02d}{:02d}_{}_{}_{:03d}h'.format(
        model, run['year'], run['month'], run['day'], run['hour'], var1var2,
        domain['name'], hour)

    # plot basic map with borders #

    if variable1['name'] == 'prec_rate'\
     or variable1['name'] == 'prec_6h':
        filename_colorpalette = 'colorscale_prec_rate.txt'
        with open(path['base'] + path['colorpalette'] + filename_colorpalette,
                  'r') as f:
            lines = f.readlines()
        rgb_colors = []
        rgb_colors.append([0, 0, 0,
                           0])  # color for under the lowest value, transparent
        for i, line in enumerate(lines):
            rgb_colors.append([
                float(line[0:3]) / 255,
                float(line[4:7]) / 255,
                float(line[8:11]) / 255, 1
            ])
        rgb_colors.append(
            rgb_colors[-1]
        )  # add highest loaded color to color for over the highest value
        levels1 = ([0.1, 0.2, 0.3, 0.5, 1, 2, 3, 5, 10, 20, 30, 50])
        lbStride_value = 1

    elif variable1['name'] == 't_850hPa':
        rgb_colors = []
        rgb_colors.append(
            [0, 0, 0])  # placeholder for color for under the lowest value
        for i in range(10):
            rgb_colors.append(
                list(
                    cmasher.take_cmap_colors('cmr.flamingo',
                                             10,
                                             cmap_range=(0.45, 0.88))[i]))
        for i in range(2, 12):
            rgb_colors.append(
                list(
                    palettable.colorbrewer.sequential.Purples_9.
                    get_mpl_colormap(N=14)(i)[:3]))
        rgb_colors.append(list(np.array([60, 53, 139]) / 255))
        rgb_colors.append(list(np.array([65, 69, 171]) / 255))
        rgb_colors.append(list(np.array([68, 86, 199]) / 255))
        for i in range(2, 19):
            rgb_colors.append(
                list(
                    palettable.colorbrewer.diverging.Spectral_10.
                    get_mpl_colormap(N=19).reversed()(i)[:3]))
        for i in range(1, 11):
            rgb_colors.append(
                list(
                    palettable.cartocolors.sequential.Burg_7.get_mpl_colormap(
                        N=11).reversed()(i)[:3]))
        rgb_colors[0] = rgb_colors[
            1]  # copy lowest loaded color to color for under the lowest value
        rgb_colors.append(
            rgb_colors[-1]
        )  # add highest loaded color to color for over the highest value
        rgb_colors[31] = list(np.array([255, 255, 160]) / 255)
        rgb_colors[32] = list(np.array([247, 230, 128]) / 255)
        levels1 = np.arange(-25, 25 + 1, 1)
        lbStride_value = 5

    elif variable1['name'] == 'theta_e_850hPa':
        rgb_colors = []
        rgb_colors.append(
            [0, 0, 0])  # placeholder for color for under the lowest value
        for i in range(5):
            rgb_colors.append(
                list(
                    cmasher.take_cmap_colors('cmr.flamingo',
                                             5,
                                             cmap_range=(0.65, 0.93))[i]))
        for i in range(4, 13):
            rgb_colors.append(
                list(
                    palettable.colorbrewer.sequential.Purples_9.
                    get_mpl_colormap(N=16)(i)[:3]))
        for i in range(26):
            rgb_colors.append(
                list(
                    palettable.colorbrewer.diverging.Spectral_10.
                    get_mpl_colormap(N=26).reversed()(i)[:3]))
        for i in range(1, 11):
            rgb_colors.append(
                list(
                    palettable.cartocolors.sequential.Burg_7.get_mpl_colormap(
                        N=11).reversed()(i)[:3]))
        for i in range(2, 2 + 5):
            rgb_colors.append(
                list(
                    palettable.scientific.sequential.Turku_10.get_mpl_colormap(
                        N=12).reversed()(i)[:3]))
        rgb_colors[0] = rgb_colors[
            1]  # copy lowest loaded color to color for under the lowest value
        rgb_colors.append(
            rgb_colors[-1]
        )  # add highest loaded color to color for over the highest value
        rgb_colors[27] = list(np.array([255, 255, 160]) / 255)
        rgb_colors[28] = list(np.array([247, 237, 128]) / 255)
        levels1 = np.arange(-20, 90 + 1, 2)
        lbStride_value = 5

    elif variable1['name'] == 'wind_300hPa':
        rgb_colors = []
        rgb_colors.append([0, 0, 0,
                           0])  # color for under the lowest value, transparent
        for i in range(1, 8):
            rgb_colors.append(
                list(
                    palettable.cmocean.sequential.Ice_10.get_mpl_colormap(
                        N=10).reversed()(i)[:3]) + [1])
        rgb_colors.append(
            rgb_colors[-1]
        )  # add highest loaded color to color for over the highest value
        levels1 = (list(range(120, 330 + 1, 30)))
        lbStride_value = 1

    elif variable1['name'] == 'cape_ml':
        rgb_colors = []
        rgb_colors.append([0, 0, 0,
                           0])  # color for under the lowest value, transparent
        for i in range(2, 7):
            rgb_colors.append(
                list(
                    palettable.scientific.sequential.Tokyo_7.get_mpl_colormap(
                        N=7)(i)[:3]) + [1])
        for i in range(1, 17, 3):
            rgb_colors.append(
                list(
                    palettable.cmocean.sequential.Thermal_20.get_mpl_colormap(
                        N=22).reversed()(i)[:3]) + [1])
        for i in range(9, 18, 4):
            rgb_colors.append(
                list(
                    palettable.cmocean.sequential.Ice_20.get_mpl_colormap(
                        N=20)(i)[:3]) + [1])
        rgb_colors.append(
            rgb_colors[-1]
        )  # add highest loaded color to color for over the highest value
        rgb_colors[1] = list(np.array([138, 98, 110]) / 255) + [1]
        rgb_colors[10] = list(np.array([142, 69, 139]) / 255) + [1]
        #levels1 = ([0,100,200,350,530,750,1000,1300,1630,2000,2400,2850,3330,3850,4400,5000])  # follows (wmax)**2
        levels1 = ([
            100, 200, 350, 500, 750, 1000, 1300, 1600, 2000, 2400, 2800, 3300,
            3800, 4400, 5000
        ])  # rounded to be pretty
        lbStride_value = 1

        #rgb_arr = np.array(rgb_colors)
        #np.savetxt("colorpalette_marco_cape_ml.txt", np.around(rgb_arr[3:-1]*255,0), fmt='%2d', delimiter = ",")

    elif variable1['name'] == 'synth_bt_ir10.8':
        filename_colorpalette = 'rainbowIRsummer.txt'
        with open(path['base'] + path['colorpalette'] + filename_colorpalette,
                  'r') as f:
            lines = f.readlines()
        rgb_colors = []
        rgb_colors.append(list(np.array([118, 39, 118]) / 255))
        for i, line in enumerate(lines):
            if i % 14 == 0 and i > 70:
                rgb_colors.append(
                    [float(line[:10]),
                     float(line[11:21]),
                     float(line[22:32])])
        rgb_colors.append(list(np.array([35, 244, 255]) / 255))
        num_bw_colors = 30
        for i in range(num_bw_colors + 1):
            rgb_colors.append([
                1 - i / num_bw_colors, 1 - i / num_bw_colors,
                1 - i / num_bw_colors
            ])
        rgb_colors.append(
            rgb_colors[-1]
        )  # add highest loaded color to color for over the highest value
        levels1 = (list(range(-90, -20, 1)) + list(range(-20, 40 + 1, 2)))
        lbStride_value = 10

    elif variable1['name'] == 'prec_24h'\
     or variable1['name'] == 'prec_sum':
        filename_colorpalette = 'colorscale_prec24h.txt'
        with open(path['base'] + path['colorpalette'] + filename_colorpalette,
                  'r') as f:
            lines = f.readlines()
        rgb_colors = []
        rgb_colors.append([0, 0, 0,
                           0])  # color for under the lowest value, transparent
        for i, line in enumerate(lines):
            rgb_colors.append([
                float(line[0:3]) / 255,
                float(line[4:7]) / 255,
                float(line[8:11]) / 255, 1
            ])
        rgb_colors.append(
            rgb_colors[-1]
        )  # add highest loaded color to color for over the highest value

        levels1 = ([
            1, 10, 20, 40, 60, 80, 100, 120, 140, 160, 180, 200, 250, 300, 400
        ])
        lbStride_value = 1

    elif variable1['name'] == 'vmax_10m':
        filename_colorpalette = 'colorscale_vmax.txt'
        with open(path['base'] + path['colorpalette'] + filename_colorpalette,
                  'r') as f:
            lines = f.readlines()
        rgb_colors = []
        rgb_colors.append(
            [0, 0, 0])  # placeholder for color for under the lowest value
        for i in range(0, 11):  # load colors from palettable
            rgb_colors.append(
                list(
                    cmasher.take_cmap_colors('cmr.chroma',
                                             11,
                                             cmap_range=(0.20,
                                                         0.95))[::-1][i]))
        for i in range(0, 3):  # load colors from palettable
            rgb_colors.append(
                list(
                    cmasher.take_cmap_colors('cmr.freeze',
                                             3,
                                             cmap_range=(0.40, 0.90))[i]))
        for i in range(0, 2):  # load colors from palettable
            rgb_colors.append(
                list(
                    cmasher.take_cmap_colors('cmr.flamingo',
                                             2,
                                             cmap_range=(0.55,
                                                         0.80))[::-1][i]))
        rgb_colors[0] = rgb_colors[
            1]  # copy lowest loaded color to color for under the lowest value
        rgb_colors.append(
            rgb_colors[-1]
        )  # add highest loaded color to color for over the highest value
        levels1 = ([
            0, 6, 12, 20, 29, 39, 50, 62, 75, 89, 103, 118, 154, 178, 209, 251,
            300
        ])
        lbStride_value = 1

    elif variable1['name'] == 'shear_200-850hPa':
        filename_colorpalette = 'colorscale_shear_200-850hPa.txt'
        with open(path['base'] + path['colorpalette'] + filename_colorpalette,
                  'r') as f:
            lines = f.readlines()
        rgb_colors = []
        rgb_colors.append([1, 1, 1])
        for i, line in enumerate(lines):
            rgb_colors.append([
                float(line[0:3]) / 255,
                float(line[4:7]) / 255,
                float(line[8:11]) / 255
            ])
        rgb_colors.append([0, 0, 1])
        levels1 = (list(np.arange(0, 30, 2.5)) + list(range(30, 50 + 1, 5)) +
                   [99])
        lbStride_value = 1

    elif variable1['name'][:2] == 'pv'\
     and variable1['name'][-1:] == 'K':
        filename_colorpalette = 'colorscale_ipv_eth.txt'
        with open(path['base'] + path['colorpalette'] + filename_colorpalette,
                  'r') as f:
            lines = f.readlines()
        rgb_colors = []
        rgb_colors.append(
            [0, 0, 0])  # placeholder for color for under the lowest value
        for i, line in enumerate(lines):
            rgb_colors.append([
                float(line[0:3]) / 255,
                float(line[4:7]) / 255,
                float(line[8:11]) / 255
            ])
        rgb_colors[0] = rgb_colors[
            1]  # copy lowest loaded color to color for under the lowest value
        rgb_colors.append(
            rgb_colors[-1]
        )  # add highest loaded color to color for over the highest value
        levels1 = ([-1, -0.5, 0.2, 0.7, 1, 1.5, 2, 3, 4, 5, 6, 7, 8, 9, 10])
        lbStride_value = 1

    elif variable1['name'][:5] == 'theta'\
     and variable1['name'][-3:] == 'PVU':
        rgb_colors = []
        rgb_colors.append(
            [0, 0, 0])  # placeholder for color for under the lowest value
        for i in range(30):
            rgb_colors.append(
                list(
                    palettable.colorbrewer.diverging.RdYlBu_10.
                    get_mpl_colormap(N=30)(i)[:3]))
        rgb_colors[0] = rgb_colors[
            1]  # copy lowest loaded color to color for under the lowest value
        rgb_colors.append(
            rgb_colors[-1]
        )  # add highest loaded color to color for over the highest value
        levels1 = np.arange(270, 420 + 1, 5)
        #levels1 = np.arange(300, 360+1, 20)
        lbStride_value = 2

    mpres = Ngl.Resources()
    mpres.mpProjection = domain['projection']

    if domain['limits_type'] == 'radius':
        mpres.mpLimitMode = 'LatLon'
        mpres.mpCenterLonF = domain['centerlon']
        mpres.mpCenterLatF = domain['centerlat']
        cutout_plot = dict(
            lat_min=float(
                np.where(domain['centerlat'] - domain['radius'] / 111.2 < -90,
                         -90, domain['centerlat'] - domain['radius'] / 111.2)),
            lat_max=float(
                np.where(domain['centerlat'] + domain['radius'] / 111.2 > 90,
                         90, domain['centerlat'] + domain['radius'] / 111.2)),
        )
        cutout_plot['lon_min'] = float(np.where(cutout_plot['lat_min'] <= -90 or cutout_plot['lat_max'] >= 90,
                                       0,
                                       domain['centerlon'] - domain['radius'] \
                                        / (111.2 * np.cos(domain['centerlat']*np.pi/180))))
        cutout_plot['lon_max'] = float(np.where(cutout_plot['lat_min'] <= -90 or cutout_plot['lat_max'] >= 90,
                                       360,
                                       domain['centerlon'] + domain['radius'] \
                                        / (111.2 * np.cos(domain['centerlat']*np.pi/180))))
        mpres.mpMinLonF = cutout_plot['lon_min']
        mpres.mpMaxLonF = cutout_plot['lon_max']
        mpres.mpMinLatF = cutout_plot['lat_min']
        mpres.mpMaxLatF = cutout_plot['lat_max']

    elif domain['limits_type'] == 'deltalatlon':
        mpres.mpLimitMode = 'LatLon'
        mpres.mpCenterLonF = 0
        mpres.mpCenterLatF = 0
        mpres.mpMinLonF = domain['centerlon'] - domain['deltalon_deg']
        mpres.mpMaxLonF = domain['centerlon'] + domain['deltalon_deg']
        mpres.mpMinLatF = domain['centerlat'] - domain['deltalat_deg']
        mpres.mpMaxLatF = domain['centerlat'] + domain['deltalat_deg']

    elif domain['limits_type'] == 'angle':
        mpres.mpLimitMode = 'Angles'
        mpres.mpCenterLonF = domain['centerlon']
        mpres.mpCenterLatF = domain['centerlat']
        mpres.mpLeftAngleF = domain['angle']
        mpres.mpRightAngleF = domain['angle']
        mpres.mpTopAngleF = domain['angle']
        mpres.mpBottomAngleF = domain['angle']

    mpres.nglMaximize = False
    mpres.vpXF = 0.001
    mpres.vpYF = 1.00
    mpres.vpWidthF = 0.88
    mpres.vpHeightF = 1.00

    mpres.mpLandFillColor = list(np.array([255, 225, 171]) / 255)
    mpres.mpOceanFillColor = [1, 1, 1]
    mpres.mpInlandWaterFillColor = [1, 1, 1]

    mpres.mpFillOn = True
    mpres.mpGridAndLimbOn = False
    mpres.mpGreatCircleLinesOn = False

    mpres.mpDataBaseVersion = 'MediumRes'
    mpres.mpDataSetName = 'Earth..4'
    mpres.mpOutlineBoundarySets = 'national'
    mpres.mpGeophysicalLineColor = 'black'
    mpres.mpNationalLineColor = 'black'
    mpres.mpGeophysicalLineThicknessF = 1.5 * domain['plot_width'] / 1000
    mpres.mpNationalLineThicknessF = 1.5 * domain['plot_width'] / 1000

    mpres.mpPerimOn = True
    mpres.mpPerimLineColor = 'black'
    mpres.mpPerimLineThicknessF = 8.0 * domain['plot_width'] / 1000
    mpres.tmXBOn = False
    mpres.tmXTOn = False
    mpres.tmYLOn = False
    mpres.tmYROn = False

    mpres.nglDraw = False  #-- don't draw plot
    mpres.nglFrame = False  #-- don't advance frame

    # settings for variable1 / shading #

    v1res = Ngl.Resources()
    v1res.nglFrame = False
    v1res.nglDraw = False
    v1res.sfDataArray = data_array1_cut
    v1res.sfXArray = clon_cut
    v1res.sfYArray = clat_cut
    v1res.sfMissingValueV = 9999
    #v1res.cnFillBackgroundColor = 'transparent'
    v1res.cnMissingValFillColor = 'Gray80'
    v1res.cnFillColors = np.array(rgb_colors)

    v1res.cnLinesOn = False
    v1res.cnFillOn = True
    v1res.cnLineLabelsOn = False
    if not variable1['load_global_field']:
        v1res.cnFillMode = 'RasterFill'
    elif model == 'icon-eu-det':
        v1res.cnFillMode = 'RasterFill'
    elif model == 'icon-global-det':
        v1res.cnFillMode = 'CellFill'
        v1res.sfXCellBounds = vlon_cut
        v1res.sfYCellBounds = vlat_cut
    #v1res.cnFillOpacityF        = 0.5
    #v1res.cnFillDrawOrder       = 'Predraw'
    v1res.cnLevelSelectionMode = 'ExplicitLevels'
    v1res.cnLevels = levels1

    v1res.lbLabelBarOn = True
    v1res.lbAutoManage = False
    v1res.lbOrientation = 'vertical'
    v1res.lbLabelOffsetF = 0.04  # minor axis fraction: the distance between colorbar and numbers
    v1res.lbBoxMinorExtentF = 0.20  # minor axis fraction: width of the color boxes when labelbar down
    v1res.lbTopMarginF = 0.2  # make a little more space at top for the unit label
    v1res.lbRightMarginF = 0.0
    v1res.lbBottomMarginF = 0.05
    v1res.lbLeftMarginF = -0.35

    v1res.cnLabelBarEndStyle = 'ExcludeOuterBoxes'
    #if variable1['name'] == 'prec_rate' :
    #    v1res.cnLabelBarEndStyle    = 'IncludeOuterBoxes'
    #v1res.cnExplicitLabelBarLabelsOn = True
    #v1res.pmLabelBarDisplayMode =  'Always'
    v1res.pmLabelBarWidthF = 0.10
    #v1res.lbLabelStrings        = label_str_list
    v1res.lbLabelFontHeightF = 0.010
    #v1res.lbBoxCount            = 40
    v1res.lbBoxSeparatorLinesOn = False
    v1res.lbBoxLineThicknessF = 4
    #v1res.lbBoxEndCapStyle     = 'TriangleBothEnds'
    v1res.lbLabelAlignment = 'ExternalEdges'
    v1res.lbLabelStride = lbStride_value

    # settings for variable2 / contourlines #

    if variable2['name'] != '':
        v2res = Ngl.Resources()
        v2res.nglFrame = False
        v2res.nglDraw = False
        v2res.sfDataArray = data_array2_cut
        v2res.sfXArray = ll_lon_cut  #ll_lon_cyclic
        v2res.sfYArray = ll_lat_cut
        v2res.sfMissingValueV = 9999
        #v2res.trGridType        = 'TriangularMesh'
        v2res.cnFillOn = False
        v2res.cnLinesOn = True
        v2res.cnLineLabelsOn = True
        v2res.cnLineLabelPlacementMode = 'Constant'
        v2res.cnLabelDrawOrder = 'PostDraw'
        v2res.cnInfoLabelOn = False
        v2res.cnSmoothingOn = False
        v2res.cnLevelSelectionMode = 'ExplicitLevels'
        v2res.cnLineThicknessF = 3.0 * domain['plot_width'] / 1000
        v2res.cnLineLabelFontHeightF = 0.008
        v2res.cnLineDashSegLenF = 0.25

        v3res = Ngl.Resources()
        v3res.nglFrame = False
        v3res.nglDraw = False
        v3res.sfDataArray = data_array2_cut
        v3res.sfXArray = ll_lon_cut  #ll_lon_cyclic
        v3res.sfYArray = ll_lat_cut
        v3res.sfMissingValueV = 9999
        #v3res.trGridType        = 'TriangularMesh'
        v3res.cnFillOn = False
        v3res.cnLinesOn = True
        v3res.cnLineLabelsOn = True
        v3res.cnLineLabelPlacementMode = 'Constant'
        v3res.cnLabelDrawOrder = 'PostDraw'
        v3res.cnInfoLabelOn = False
        v3res.cnSmoothingOn = False
        v3res.cnLevelSelectionMode = 'ExplicitLevels'
        v3res.cnLineThicknessF = 5.0 * domain['plot_width'] / 1000
        v3res.cnLineLabelFontHeightF = 0.008
        v3res.cnLineDashSegLenF = 0.25

        if variable2['name'] == 'mslp':
            v2res.cnLevels = np.arange(900, 1100, 2)
            v2res.cnLineLabelInterval = 1
            v3res.cnLevels = np.arange(900, 1100, 10)
            v3res.cnLineLabelInterval = 1

        elif variable2['name'] == 'gph_300hPa':
            v2res.cnLevels = np.arange(780, 1000, 6)
            v2res.cnLineLabelInterval = 1
            v3res.cnLevels = np.arange(780, 1000, 24)
            v3res.cnLineLabelInterval = 1

        elif variable2['name'] == 'gph_850hPa':
            v2res.cnLevels = np.arange(100, 180, 2)
            v2res.cnLineLabelInterval = 2
            v3res.cnLevels = np.arange(100, 180, 10)
            v3res.cnLineLabelInterval = 2

        elif variable2['name'] == 'gph_700hPa':
            v2res.cnLevels = np.arange(472, 633, 2)
            v2res.cnLineLabelInterval = 1
            v3res.cnLevels = np.arange(472, 633, 8)
            v3res.cnLineLabelInterval = 1

        elif variable2['name'] == 'gph_500hPa':
            v2res.cnLevels = np.arange(472, 633, 4)
            v2res.cnLineLabelInterval = 1
            v3res.cnLevels = np.arange(472, 633, 16)
            v3res.cnLineLabelInterval = 1

        elif variable2['name'] == 'shear_0-6km':
            v4res = Ngl.Resources()
            v4res.nglFrame = False
            v4res.nglDraw = False
            v4res.sfDataArray = data_array2_cut
            v4res.sfXArray = ll_lon_cut  #ll_lon_cyclic
            v4res.sfYArray = ll_lat_cut
            v4res.sfMissingValueV = 9999
            #v4res.trGridType        = 'TriangularMesh'
            v4res.cnFillOn = False
            v4res.cnLinesOn = True
            v4res.cnLineLabelsOn = True
            v4res.cnLineLabelPlacementMode = 'Constant'
            v4res.cnLabelDrawOrder = 'PostDraw'
            v4res.cnInfoLabelOn = False
            v4res.cnSmoothingOn = False
            v4res.cnLevelSelectionMode = 'ExplicitLevels'
            v4res.cnLineLabelFontHeightF = 0.008
            v4res.cnLineDashSegLenF = 0.25
            v5res = Ngl.Resources()
            v5res.nglFrame = False
            v5res.nglDraw = False
            v5res.sfDataArray = data_array2_cut
            v5res.sfXArray = ll_lon_cut  #ll_lon_cyclic
            v5res.sfYArray = ll_lat_cut
            v5res.sfMissingValueV = 9999
            #54res.trGridType        = 'TriangularMesh'
            v5res.cnFillOn = False
            v5res.cnLinesOn = True
            v5res.cnLineLabelsOn = True
            v5res.cnLineLabelPlacementMode = 'Constant'
            v5res.cnLabelDrawOrder = 'PostDraw'
            v5res.cnInfoLabelOn = False
            v5res.cnSmoothingOn = False
            v5res.cnLevelSelectionMode = 'ExplicitLevels'
            v5res.cnLineLabelFontHeightF = 0.008
            v5res.cnLineDashSegLenF = 0.25

            v2res.cnLevels = [10]
            v2res.cnLineLabelInterval = 1
            v2res.cnLineDashSegLenF = 0.15
            v2res.cnLineThicknessF = 2.4 * domain['plot_width'] / 1000
            v3res.cnLevels = [15]
            v3res.cnLineLabelInterval = 1
            v3res.cnLineThicknessF = 4.5 * domain['plot_width'] / 1000
            v3res.cnLineDashSegLenF = 0.15
            v3res.cnLineThicknessF = 3.6 * domain['plot_width'] / 1000
            v4res.cnLevels = [20]
            v4res.cnLineLabelInterval = 1
            v4res.cnLineDashSegLenF = 0.15
            v4res.cnLineThicknessF = 5.4 * domain['plot_width'] / 1000
            v5res.cnLevels = [25]
            v5res.cnLineLabelInterval = 1
            v5res.cnLineDashSegLenF = 0.15
            v5res.cnLineThicknessF = 8.0 * domain['plot_width'] / 1000
    ''' these are settings for some experiment with lows/highs min/max pressure labels:
    v2res.cnLineLabelsOn = True
    v2res.cnLabelDrawOrder = 'PostDraw'
    v2res.cnLineLabelPerimOn = False
    v2res.cnLineLabelBackgroundColor = 'transparent'
    v2res.cnLineLabelPlacementMode = 'Computed'
    v2res.cnLineLabelDensityF = 0.2
    v2res.cnLineLabelFontHeightF = 0.010
    #v2res.cnLineDashSegLenF = 0.25

    v2res.cnLowLabelsOn = True
    #v2res.cnLowLabelPerimOn = False
    v2res.cnLowLabelString = '$ZDV$hPa'
    #v2res.cnLowLabelFontColor = 'black'
    v2res.cnLowLabelBackgroundColor = 'white'''

    # settings for unit text #

    if variable1['name'][:2] == 'pv'\
    and (domain['name'] == 'southern_south_america'\
          or domain['name'] == 'south_pole'):
        text_str = variable1['unit'] + ' * -1'
    else:
        text_str = variable1['unit']
    text_res_1 = Ngl.Resources()
    text_res_1.txFontColor = 'black'
    text_res_1.txFontHeightF = 0.013
    text_x = 0.965
    text_y = domain['text_y']

    # settings for description label #

    res_text_descr = Ngl.Resources()
    res_text_descr.txJust = 'CenterLeft'
    res_text_descr.txFontHeightF = 0.01
    res_text_descr.txFontColor = 'black'
    res_text_descr.txBackgroundFillColor = 'white'
    res_text_descr.txPerimOn = True
    res_text_descr.txPerimColor = 'black'

    text_descr_str1 = 'ICON-Global-Deterministic from {:02d}.{:02d}.{:4d} {:02d}UTC +{:d}h, '.format(
        run['day'], run['month'], run['year'], run['hour'], hour)
    if variable2['name'] == '':
        text_descr_str2 = 'Contours: {} in {}'.format(variable1['name'],
                                                      variable1['unit'])
    else:
        text_descr_str2 = 'Contours: {} in {}, Lines: {} in {}'.format(
            variable1['name'], variable1['unit'], variable2['name'],
            variable2['unit'])
    text_descr_x = 0.02
    text_descr_y = domain['text_y'] - 0.005

    # override settings for specific cases #

    if domain['name'] == 'mediterranean':
        mpres.mpPerimLineThicknessF /= 1.5
        mpres.mpGeophysicalLineThicknessF /= 1.5
        mpres.mpNationalLineThicknessF /= 1.5
        mpres.vpWidthF = 0.94
        v1res.lbLabelFontHeightF = 0.005
        v1res.pmLabelBarWidthF = 0.04
        v1res.lbLeftMarginF = -0.50
        if variable2['name'] != '':
            v2res.cnLineThicknessF /= 1.5
            v2res.cnLineLabelFontHeightF /= 1.5
            v3res.cnLineThicknessF /= 1.5
            v3res.cnLineLabelFontHeightF /= 1.5
            v2res.cnLineDashSegLenF = 0.12
            v3res.cnLineDashSegLenF = 0.12
        text_res_1.txFontHeightF = 0.007
        text_x = 0.980
        res_text_descr.txFontHeightF = 0.007
        text_descr_x = 0.005

    elif domain['name'] == 'north_pole' or domain['name'] == 'south_pole':
        if variable2['name'] == 'mslp':
            v2res.cnLevels = np.arange(900, 1100, 4)
            v3res.cnLevels = np.arange(900, 1100, 20)
        elif variable2['name'] == 'gph_300hPa':
            v2res.cnLevels = np.arange(780, 1000, 12)
            v3res.cnLevels = np.arange(780, 1000, 48)
        elif variable2['name'] == 'gph_500hPa':
            v2res.cnLevels = np.arange(472, 633, 8)
            v3res.cnLevels = np.arange(472, 633, 32)
        elif variable2['name'] == 'gph_700hPa':
            v2res.cnLevels = np.arange(472, 633, 8)
            v3res.cnLevels = np.arange(472, 633, 32)
        elif variable2['name'] == 'gph_850hPa':
            v2res.cnLevels = np.arange(102, 180, 4)
            v3res.cnLevels = np.arange(102, 180, 20)
    elif domain['name'] == 'Argentina_Central' or domain[
            'name'] == 'Argentina_Central_cerca':
        if variable2['name'] == 'gph_850hPa':
            v2res.cnLevels = np.arange(100, 180, 1)
            v3res.cnLevels = np.arange(100, 180, 5)
            v2res.cnLineLabelInterval = 1

    wks_res = Ngl.Resources()
    wks_res.wkWidth = domain['plot_width']
    wks_res.wkHeight = domain[
        'plot_width']  # the whitespace above and below the plot will be cut afterwards
    #wks_res.wkColorMap = np.array(rgb_colors)
    wks_type = 'png'
    wks = Ngl.open_wks(wks_type, path['base'] + path['plots'] + plot_name,
                       wks_res)

    basic_map = Ngl.map(wks, mpres)

    # plot subnational borders for some domains #
    '''shp_filenames = []
    if domain['name'] == 'southern_south_america'\
     or domain['name'] == 'arg_uru_braz'\
     or domain['name'] == 'argentina_central'\
     or domain['name'] == 'argentina_central_cerca':
        shp_filenames.append(['gadm36_ARG_1.shp', 0.3])
        shp_filenames.append(['gadm36_BRA_1.shp', 0.3])
        shp_filenames.append(['gadm36_CHL_1.shp', 0.3])
    elif domain['name'] == 'north_america':
        shp_filenames.append(['gadm36_USA_1.shp', 0.3])
        shp_filenames.append(['gadm36_CAN_1.shp', 0.3])
        shp_filenames.append(['gadm36_MEX_1.shp', 0.3])
    elif domain['name'] == 'eastern_asia':
        shp_filenames.append(['gadm36_CHN_1.shp', 0.3])

    for shp_filename, lineThickness in shp_filenames:
        shpf = Nio.open_file(path['base'] + path['shapefiles'] + shp_filename, 'r')
        shpf_lon = np.ravel(shpf.variables['x'][:])
        shpf_lat = np.ravel(shpf.variables['y'][:])
        shpf_segments = shpf.variables['segments'][:, 0]

        plres = Ngl.Resources()
        plres.gsLineColor = 'black'
        plres.gsLineThicknessF = lineThickness
        plres.gsSegments = shpf_segments
        Ngl.add_polyline(wks, basic_map, shpf_lon, shpf_lat, plres)'''

    # put everything together #

    contourshades_plot = Ngl.contour(wks, data_array1_cut, v1res)
    if variable2['name'] != '':
        contourlines_minor_plot = Ngl.contour(wks, data_array2_cut, v2res)
        contourlines_major_plot = Ngl.contour(wks, data_array2_cut, v3res)
        if variable2['name'] == 'shear_0-6km':
            contourlines_major2_plot = Ngl.contour(wks, data_array2_cut, v4res)
            contourlines_major3_plot = Ngl.contour(wks, data_array2_cut, v5res)

    Ngl.overlay(basic_map, contourshades_plot)
    if variable2['name'] != '':
        Ngl.overlay(basic_map, contourlines_minor_plot)
        Ngl.overlay(basic_map, contourlines_major_plot)
        if variable2['name'] == 'shear_0-6km':
            Ngl.overlay(basic_map, contourlines_major2_plot)
            Ngl.overlay(basic_map, contourlines_major3_plot)

    Ngl.draw(basic_map)
    Ngl.text_ndc(wks, text_str, text_x, text_y, text_res_1)
    #Ngl.text_ndc(wks, text_descr_str1 + text_descr_str2, text_descr_x, text_descr_y, res_text_descr)

    Ngl.frame(wks)
    Ngl.delete_wks(wks)

    # cut top and bottom whitespace of plot #

    im = Image.open(path['base'] + path['plots'] + plot_name + '.png')
    image_array = np.asarray(im.convert('L'))
    image_array = np.where(image_array < 255, 1, 0)
    image_filter = np.amax(image_array, axis=1)
    vmargins = [
        np.nonzero(image_filter)[0][0],
        np.nonzero(image_filter[::-1])[0][0]
    ]
    #print(vmargins)
    #print(im.size)

    im_cropped = Image.new(
        'RGB', (im.size[0], im.size[1] - vmargins[0] - vmargins[1]),
        (255, 255, 255))
    im_cropped.paste(
        im.crop((0, vmargins[0], im.size[0], im.size[1] - vmargins[1])),
        (0, 0))
    #print(im_cropped.size)
    im.close()
    im_cropped.save(path['base'] + path['plots'] + plot_name + '.png', 'png')
    im_cropped.close()

    return
def plot_sigmaz_relation(models,
                         plot_output_name="sigmaz_relation",
                         plot_output_path=None,
                         plot_output_format=".eps",
                         relative=False,
                         z_min=0.0,
                         z_max=0.7,
                         sigma_min=0,
                         sigma_max=4000,
                         axis=None,
                         verbose=True,
                         frb_obs=None):
    """
    Plots the Sigma-z Relation


    Parameters
    ----------
    models:

    plot_output_name: str, optional
        The name of the output plot. Default: "dmz_relation".

    plot_output_path: str, optional

    plot_output_format: str, optional

    z_min: int or float, optional
        The minimum Default: 0.0

    z_max: int or float, optional
        The maximum redshift (max x limit) for the

    """

    # Create an figure instance, but use a passed axis if given.
    if axis:
        ax = axis
    else:
        fig, ax = plt.subplots(nrows=1, ncols=1, constrained_layout=True)

    # Create a 2D image with different x-y bin sizes.
    #im = plot_tools.plot_2d_array(
    #    np.log10(models[0].Hist),
    #    xvals=models[0].z_bins,
    #    yvals=models[0].DM_bins,
    #    cmap=cmasher.arctic_r,
    #    passed_ax=ax,
    #    label="This Work",
    #    vmax=-2,
    #    vmin=-5
    #    )

    # Set up the colour bar
    #divider = make_axes_locatable(ax)
    #cax = divider.append_axes("right", size="5%", pad=0.05)
    #cbar = plt.colorbar(im, cax=cax, label=r"$\mathrm{PDF}$")
    #cbar.ax.tick_params(axis='y', direction='out')

    # Plot the 2D histogram as an image in the backgound
    for model in models:
        if model.category == '2D-hydrodynamic' and model.plot_toggle:
            print_tools.vprint(f"{model.label}", verbose=verbose)

            #filename = "RefL0100N1504_log_normal_fit_mean_std_percent.txt"
            #redshift, mean, std, percent = np.loadtxt(filename, unpack=True, skiprows=1)
            #output = open("RefL0100N1504_mean_direct_values.txt", "w")
            #output.write("Redshift Mean\n")
            #output.write("0.000 0.000\n")
            #redshift = model.z_bins + math_tools.cosmology.cMpc_to_z(100)

            #mean = np.zeros(len(model.z_bins))
            #for idx, pdf in enumerate(model.Hist.T):
            #    mean[idx] = calc_mean_from_pdf(model.DM_bins, pdf)
            #    z = redshift[idx]

            #    output.write(f"{redshift[idx]:.3f} {mean[idx]:.3f}\n")

            #output.close()

            data = np.loadtxt(
                "analysis_outputs/shuffled/ANALYSIS_RefL0100N1504_confidence_intervals.txt",
                unpack=True,
                skiprows=2)
            redshift = data[0]
            mean = data[1]
            median = data[2]

            std1_values = []
            std2_values = []
            std3_values = []
            for idx, z in enumerate(redshift):
                std1_values.append((data[3][idx], data[4][idx]))
                std2_values.append((data[5][idx], data[6][idx]))
                std3_values.append((data[7][idx], data[8][idx]))

            mean_line = ax.plot(
                redshift,
                mean,
                color='black',
                label="$\mathrm{RefL0100N1504}\ <\mathrm{DM}>$",
                linewidth=2,
                zorder=1)

            #std1_values = []
            #std2_values = []
            #std3_values = []
            #for z_idx, pdf in enumerate(model.Hist.T):
            #lower_idx, upper_idx = calc_std_bin_idx_from_pdf(pdf)
            #lower_std, upper_std = calc_std_values(model.DM_bins, lower_idx, upper_idx)
            #std1_values.append((lower_std, upper_std))

            #lower_idx, upper_idx = calc_std_bin_idx_from_pdf(pdf, num_sigma=2)
            #lower_std, upper_std = calc_std_values(model.DM_bins, lower_idx, upper_idx)
            #std2_values.append((lower_std, upper_std))

            #lower_idx, upper_idx = calc_std_bin_idx_from_pdf(pdf, num_sigma=3)
            #lower_std, upper_std = calc_std_values(model.DM_bins, lower_idx, upper_idx)
            #std3_values.append((lower_std, upper_std))

            if frb_obs is not None:
                frb_handles = []
                frb_labels = []

                frb_repeater_list = []
                frb_non_repeater_list = []
                for frb in frb_obs_list:
                    if frb["Repeater"]:
                        frb_repeater_list.append(frb)
                    else:
                        frb_non_repeater_list.append(frb)

                colours = cmasher.take_cmap_colors('cmr.sunburst',
                                                   2,
                                                   cmap_range=(0.15, 0.75),
                                                   return_fmt='hex')

                for idx, frb in enumerate(frb_repeater_list):
                    redshift = frb["z"]
                    dm = frb["DM"] - frb["DM_MW"]

                    lower_errorbar = np.array([130])
                    upper_errorbar = frb["DM_MW"]
                    errors = (lower_errorbar, upper_errorbar)

                    marker = "d"
                    colour = colours[0]

                    im = ax.errorbar(redshift,
                                     dm,
                                     yerr=errors,
                                     color=colour,
                                     marker=marker,
                                     markersize=5,
                                     zorder=10000)

                frb_handles.append(im)
                frb_labels.append("Repeater")

                for idx, frb in enumerate(frb_non_repeater_list):
                    redshift = frb["z"]
                    dm = frb["DM"] - frb["DM_MW"]

                    lower_errorbar = np.array([130])
                    upper_errorbar = frb["DM_MW"]
                    errors = (lower_errorbar, upper_errorbar)

                    marker = "o"
                    colour = colours[1]

                    im = ax.errorbar(redshift,
                                     dm,
                                     yerr=errors,
                                     color=colour,
                                     marker=marker,
                                     markersize=5,
                                     zorder=10000)

                frb_handles.append(im)
                frb_labels.append("Non-Repeater")

            std1_values = np.array(std1_values)
            std2_values = np.array(std2_values)
            std3_values = np.array(std3_values)

            sigma_colours = np.array(
                list(
                    map(mpl.colors.to_hex,
                        cmasher.ocean(np.linspace(0.20, 0.50, 3)))))

            sig3 = ax.fill_between(model.z_bins,
                                   std3_values.T[0],
                                   std3_values.T[1],
                                   alpha=0.35,
                                   color=sigma_colours[2],
                                   label=f"{model.label} $3 \sigma$")
            sig2 = ax.fill_between(model.z_bins,
                                   std2_values.T[0],
                                   std2_values.T[1],
                                   alpha=0.35,
                                   color=sigma_colours[1],
                                   label=f"{model.label} $2 \sigma$")
            sig1 = ax.fill_between(model.z_bins,
                                   std1_values.T[0],
                                   std1_values.T[1],
                                   alpha=0.35,
                                   color=sigma_colours[0],
                                   label=f"{model.label} $1 \sigma$")

            #ax.scatter(redshift, dm, color=frb["Color"], marker='o', label=frb["Label"], zorder=10000)

    ax.set_xlim(z_min, z_max)
    ax.set_ylim(sigma_min, sigma_max)

    p13 = cosmology.Planck13
    #ax.set_xlim(0, 0.7)
    ax.set_ylim(0.0001, 1100)
    ax1_twin = math_tools.cosmology.make_lookback_time_axis(ax,
                                                            cosmo=p13,
                                                            z_range=(z_min,
                                                                     z_max))
    ax1_twin.set_xlabel("$\mathrm{Lookback\ Time\ [Gyr]}$")

    # This forces the x-tick labels to be integers for consistancy.
    # This fixes a problem I was having where it changed from ints to floats
    # seemingly randomly for different number of models.
    #ax.xaxis.set_major_locator(MaxNLocator(integer=False))

    ax.set_xlabel(r"$\rm{Redshift}$")
    #ax.set_ylabel(r"$\rm{DM_{Obs} - DM_{MW,\ NE2001}\ \left[pc\ cm^{-3}\right] }$")
    ax.set_ylabel(r"$\rm{DM_{cosmic}\ \left[pc\ cm^{-3}\right] }$")

    sigma_colours = np.array(
        list(map(mpl.colors.to_hex, cmasher.ocean(np.linspace(0.20, 0.50,
                                                              3)))))

    mean_line = mlines.Line2D([], [],
                              color='black',
                              linewidth=2,
                              label=r"$\langle \mathrm{DM_{cosmic}} \rangle$")
    sig1_legend = mpatches.Patch(color=sigma_colours[0],
                                 label=r"$1\ \sigma_\mathrm{CI}$",
                                 alpha=0.35)
    sig2_legend = mpatches.Patch(color=sigma_colours[1],
                                 label=r"$2\ \sigma_\mathrm{CI}$",
                                 alpha=0.35)
    sig3_legend = mpatches.Patch(color=sigma_colours[2],
                                 label=r"$3\ \sigma_\mathrm{CI}$",
                                 alpha=0.35)

    # Create legends for the FRBs and EAGLE data
    # They need to be seperate to make better use of space.
    sigma_legend = ax.legend(
        handles=[mean_line, sig1_legend, sig2_legend, sig3_legend],
        loc='upper left',
        frameon=False,
        fontsize=11)
    frb_legend = ax.legend(handles=frb_handles,
                           labels=frb_labels,
                           loc='lower right',
                           fontsize=11,
                           frameon=False)

    # Add the legends manually to the current Axes.
    ax.add_artist(sigma_legend)
    ax.add_artist(frb_legend)

    output_file_name = os.path.join(plot_output_path,
                                    f"{plot_output_name}{plot_output_format}")
    plt.savefig(output_file_name, dpi=300)