示例#1
0
def entry_for_cc_canesm2_gl():
    """
    for CanESM2 driven CRCM5_NEMO simulation
    """
    data_root = common_params.data_root
    label_to_datapath = OrderedDict([
        (common_params.crcm_nemo_cur_label, data_root /
         "lake_effect_analysis_CRCM5_NEMO_CanESM2_RCP85_1989-2010_1989-2010/merged/"
         ),
        (common_params.crcm_nemo_fut_label, data_root /
         "lake_effect_analysis_CRCM5_NEMO_CanESM2_RCP85_2079-2100_2079-2100/merged/"
         ),
    ])

    cur_st_date = datetime(1989, 1, 1)
    cur_en_date = datetime(2011, 1, 1)  # end date not inclusive

    fut_st_date = datetime(2079, 1, 1)
    fut_en_date = datetime(2101, 1, 1)  # end date not inclusive

    cur_period = Period(cur_st_date, cur_en_date)
    fut_period = Period(fut_st_date, fut_en_date)

    periods_info = CcPeriodsInfo(cur_period=cur_period, fut_period=fut_period)

    season_to_months = OrderedDict([("ND", [11, 12]), ("JF", [1, 2]),
                                    ("MA", [3, 4])])

    var_pairs = [("hles_snow", "TT"), ("hles_snow", "PR"),
                 ("hles_snow", "lake_ice_fraction")]

    var_display_names = {
        "hles_snow": "HLES",
        "lake_ice_fraction": "Mean Lake ice \nfraction",
        "TT": "2m air\n temperature",
        "PR": "total\nprecipitation"
    }

    plot_utils.apply_plot_params(width_cm=25, height_cm=25, font_size=8)

    gl_mask = get_gl_mask(label_to_datapath[common_params.crcm_nemo_cur_label])
    hles_region_mask = get_mask_of_points_near_lakes(gl_mask,
                                                     npoints_radius=20)

    main(label_to_data_path=label_to_datapath,
         var_pairs=var_pairs,
         periods_info=periods_info,
         vname_display_names=var_display_names,
         season_to_months=season_to_months,
         hles_region_mask=hles_region_mask,
         lakes_mask=gl_mask)
def entry_for_cc_canesm2_gl():
    """
    for CanESM2 driven CRCM5_NEMO simulation
    """
    data_root = common_params.data_root
    label_to_datapath = OrderedDict([
        (common_params.crcm_nemo_cur_label,
         data_root / "lake_effect_analysis_CRCM5_NEMO_CanESM2_RCP85_1989-2010_1989-2010/merged/"),
        (common_params.crcm_nemo_fut_label,
         data_root / "lake_effect_analysis_CRCM5_NEMO_CanESM2_RCP85_2079-2100_2079-2100/merged/"),
    ])

    cur_st_date = datetime(1989, 1, 1)
    cur_en_date = datetime(2011, 1, 1)  # end date not inclusive

    fut_st_date = datetime(2079, 1, 1)
    fut_en_date = datetime(2101, 1, 1)  # end date not inclusive

    cur_period = Period(cur_st_date, cur_en_date)
    fut_period = Period(fut_st_date, fut_en_date)

    periods_info = CcPeriodsInfo(cur_period=cur_period, fut_period=fut_period)

    season_to_months = OrderedDict([
        ("ND", [11, 12]),
        ("JF", [1, 2]),
        ("MA", [3, 4])
    ])

    var_pairs = [("hles_snow", "TT"), ("hles_snow", "PR"), ("hles_snow", "lake_ice_fraction")]

    var_display_names = {
        "hles_snow": "HLES",
        "lake_ice_fraction": "Mean Lake ice \nfraction",
        "TT": "2m air\n temperature",
        "PR": "total\nprecipitation"
    }

    plot_utils.apply_plot_params(width_cm=25, height_cm=25, font_size=8)

    gl_mask = get_gl_mask(label_to_datapath[common_params.crcm_nemo_cur_label])
    hles_region_mask = get_mask_of_points_near_lakes(gl_mask, npoints_radius=20)


    main(label_to_data_path=label_to_datapath, var_pairs=var_pairs, periods_info=periods_info,
         vname_display_names=var_display_names, season_to_months=season_to_months,
         hles_region_mask=hles_region_mask, lakes_mask=gl_mask)
def main(varname=""):
    plot_utils.apply_plot_params(width_cm=22, height_cm=5, font_size=8)
    # series = get_monthly_accumulations_area_avg(data_dir="/HOME/huziy/skynet3_rech1/Netbeans Projects/Python/RPN/lake_effect_analysis_Obs_monthly_1980-2009",
    #                                             varname=varname)

    # series = get_monthly_accumulations_area_avg(data_dir="/RESCUE/skynet3_rech1/huziy/Netbeans Projects/Python/RPN/lake_effect_analysis_CRCM5_NEMO_1980-2009_monthly",
    #                                             varname=varname)

    # series = get_monthly_accumulations_area_avg(data_dir="/RESCUE/skynet3_rech1/huziy/Netbeans Projects/Python/RPN/lake_effect_analysis_CRCM5_HL_1980-2009_monthly",
    #                                             varname=varname)

    selected_months = [9, 10, 11, 12, 1, 2, 3, 4, 5]



    data_root = common_params.data_root

    label_to_datapath = OrderedDict([
        # ("Obs", "/HOME/huziy/skynet3_rech1/Netbeans Projects/Python/RPN/lake_effect_analysis_Obs_monthly_1980-2009"),
        # ("Obs", "/HOME/huziy/skynet3_rech1/Netbeans Projects/Python/RPN/lake_effect_analysis_daily_Obs_monthly_icefix_1980-2009"),
        (common_params.crcm_nemo_cur_label, data_root / "lake_effect_analysis_CRCM5_NEMO_CanESM2_RCP85_1989-2010_1989-2010"),
        (common_params.crcm_nemo_fut_label, data_root / "lake_effect_analysis_CRCM5_NEMO_CanESM2_RCP85_2079-2100_2079-2100"),
    ])


    label_to_series = OrderedDict()
    label_to_color = {
        common_params.crcm_nemo_cur_label: "skyblue",
        common_params.crcm_nemo_fut_label: "salmon"

    }

    gl_mask = get_gl_mask(label_to_datapath[common_params.crcm_nemo_cur_label] / "merged")
    hles_region_mask = get_mask_of_points_near_lakes(gl_mask, npoints_radius=20)

    # select a file from the directory
    sel_file = None
    for f in label_to_datapath[common_params.crcm_nemo_cur_label].iterdir():
        sel_file = f

    with xarray.open_dataset(sel_file) as ds:
        hles_region_mask_lons, hles_region_mask_lats = [ds[k].values for k in ["lon", "lat"]]

    for label, datapath in label_to_datapath.items():
        series = get_monthly_accumulations_area_avg(data_dir=datapath, varname=varname,
                                                    fname_suffix="_daily.nc",
                                                    region_of_interest_mask=hles_region_mask)
        label_to_series[label] = series


    #
    # print(series)
    # assert isinstance(series, pd.Series)
    # ax = series.plot(kind="bar", width=1)
    #
    # ax.set_ylabel("%")
    # ax.set_xlabel("Month")

    gs = GridSpec(1, 2, wspace=0.)

    fig = plt.figure()
    ax = fig.add_subplot(gs[0, 1])

    start_date = datetime(2001, 10, 1)

    dates = [start_date.replace(month=(start_date.month + i) % 13 + int((start_date.month + i) % 13 == 0),
                                year=start_date.year + (start_date.month + i) // 13) for i in range(13)]


    def format_month_label(x, pos):
        print(num2date(x))
        return "{:%b}".format(num2date(x))



    # calculate bar widths
    dates_num = date2num(dates)
    width = np.diff(dates_num) / (len(label_to_series) * 1.5)
    width = np.array([width[0] for _ in width])


    # select the months
    width = np.array([w for w, d in zip(width, dates) if d.month in selected_months])
    dates = [d for d in dates[:-1] if d.month in selected_months]
    dates_num = date2num(dates)


    label_to_handle = OrderedDict()


    label_to_annual_hles = OrderedDict()

    for i, (label, series) in enumerate(label_to_series.items()):
        values = [series[d.month] for d in dates]

        # convert to percentages
        values_sum = sum(values)

        # save the total annual hles for later reuse
        label_to_annual_hles[label] = values_sum

        values = [v / values_sum * 100 for v in values]

        print(label, values)
        print(f"sum(values) = {sum(values)}")

        h = ax.bar(dates_num + i * width, values, width=width, align="edge", linewidth=0.5,
               edgecolor="k", facecolor=label_to_color[label], label=label, zorder=10)
        label_to_handle[label] = h

    ax.set_ylabel("% of total HLES")
    ax.set_title("(b) Monthly HLES distribution")


    ax.xaxis.set_major_formatter(FuncFormatter(func=format_month_label))
    ax.xaxis.set_major_locator(MonthLocator(bymonthday=int(sum(width[:len(label_to_series)]) / 2.) + 1))
    ax.spines['right'].set_visible(False)
    ax.spines['top'].set_visible(False)
    # ax.set_title(common_params.varname_to_display_name[varname])
    ax.yaxis.grid(True, linestyle="--", linewidth=0.5)
    # ax.text(1, 1, "(a)", fontdict=dict(weight="bold"), transform=ax.transAxes, va="top", ha="right")
    ax_with_legend = ax

    # area average annual total HLES
    text_align_props = dict(transform=ax.transAxes, va="bottom", ha="right")

    cur_hles_annual = label_to_annual_hles[common_params.crcm_nemo_cur_label]
    fut_hles_annual = label_to_annual_hles[common_params.crcm_nemo_fut_label]

    ax.text(1, 0.2, r"$\Delta_{\rm total}$" + f"({(fut_hles_annual - cur_hles_annual) / cur_hles_annual * 100:.1f}%)",
            **text_align_props, fontdict=dict(size=6))

    # Plot the domain and the HLES region of interest
    ax = fig.add_subplot(gs[0, 0])
    topo_nc_file = data_root / "geophys_452x260_me.nc"
    ax = plot_domain_and_interest_region(ax, topo_nc_file)
    ax.set_title("(a) Experimental domain")


    # Add a common legend
    labels = list(label_to_handle)
    handles = [label_to_handle[l] for l in labels]
    ax_with_legend.legend(handles, labels, bbox_to_anchor=(0, -0.18), loc="upper left", borderaxespad=0., ncol=2)

    # ax.grid()
    sel_months_str = "_".join([str(m) for m in selected_months])

    common_params.img_folder.mkdir(exist_ok=True)
    img_file = common_params.img_folder / f"{varname}_histo_cc_m{sel_months_str}_domain.png"
    print(f"Saving plot to {img_file}")
    fig.savefig(img_file, **common_params.image_file_options)
def main(varname=""):
    plot_utils.apply_plot_params(width_cm=18, height_cm=5.5, font_size=8)
    # series = get_monthly_accumulations_area_avg(data_dir="/HOME/huziy/skynet3_rech1/Netbeans Projects/Python/RPN/lake_effect_analysis_Obs_monthly_1980-2009",
    #                                             varname=varname)

    # series = get_monthly_accumulations_area_avg(data_dir="/RESCUE/skynet3_rech1/huziy/Netbeans Projects/Python/RPN/lake_effect_analysis_CRCM5_NEMO_1980-2009_monthly",
    #                                             varname=varname)

    # series = get_monthly_accumulations_area_avg(data_dir="/RESCUE/skynet3_rech1/huziy/Netbeans Projects/Python/RPN/lake_effect_analysis_CRCM5_HL_1980-2009_monthly",
    #                                             varname=varname)

    selected_months = [9, 10, 11, 12, 1, 2, 3, 4, 5]

    data_root = common_params.data_root

    label_to_datapath = OrderedDict([
        # ("Obs", "/HOME/huziy/skynet3_rech1/Netbeans Projects/Python/RPN/lake_effect_analysis_Obs_monthly_1980-2009"),
        # ("Obs", "/HOME/huziy/skynet3_rech1/Netbeans Projects/Python/RPN/lake_effect_analysis_daily_Obs_monthly_icefix_1980-2009"),
        (common_params.crcm_nemo_cur_label, data_root /
         "lake_effect_analysis_CRCM5_HL_CanESM2_RCP85_1989-2010_1989-2010"),
        (common_params.crcm_nemo_fut_label, data_root /
         "lake_effect_analysis_CRCM5_HL_CanESM2_RCP85_2079-2100_2079-2100"),
    ])

    label_to_series = OrderedDict()
    label_to_color = {
        common_params.crcm_nemo_cur_label: "skyblue",
        common_params.crcm_nemo_fut_label: "salmon"
    }

    gl_mask = get_gl_mask(
        label_to_datapath[common_params.crcm_nemo_cur_label] / "merged")
    hles_region_mask = get_mask_of_points_near_lakes(gl_mask,
                                                     npoints_radius=10)

    for label, datapath in label_to_datapath.items():
        series = get_monthly_accumulations_area_avg(
            data_dir=datapath,
            varname=varname,
            fname_suffix="_daily.nc",
            region_of_interest_mask=hles_region_mask)
        label_to_series[label] = series

    #
    # print(series)
    # assert isinstance(series, pd.Series)
    # ax = series.plot(kind="bar", width=1)
    #
    # ax.set_ylabel("%")
    # ax.set_xlabel("Month")

    gs = GridSpec(1, 2, wspace=0.4)

    fig = plt.figure()
    ax = fig.add_subplot(gs[0, 0])

    start_date = datetime(2001, 10, 1)

    dates = [
        start_date.replace(month=(start_date.month + i) % 13 +
                           int((start_date.month + i) % 13 == 0),
                           year=start_date.year + (start_date.month + i) // 13)
        for i in range(13)
    ]

    def format_month_label(x, pos):
        print(num2date(x))
        return "{:%b}".format(num2date(x))

    # calculate bar widths
    dates_num = date2num(dates)
    width = np.diff(dates_num) / (len(label_to_series) * 1.5)
    width = np.array([width[0] for _ in width])

    # select the months
    width = np.array(
        [w for w, d in zip(width, dates) if d.month in selected_months])
    dates = [d for d in dates[:-1] if d.month in selected_months]
    dates_num = date2num(dates)

    label_to_handle = OrderedDict()

    label_to_annual_hles = OrderedDict()

    for i, (label, series) in enumerate(label_to_series.items()):
        values = [series[d.month] for d in dates]

        # convert to percentages
        values_sum = sum(values)

        # save the total annual hles for later reuse
        label_to_annual_hles[label] = values_sum

        values = [v / values_sum * 100 for v in values]

        print(label, values)
        print(f"sum(values) = {sum(values)}")

        h = ax.bar(dates_num + i * width,
                   values,
                   width=width,
                   align="edge",
                   linewidth=0.5,
                   edgecolor="k",
                   facecolor=label_to_color[label],
                   label=label,
                   zorder=10)
        label_to_handle[label] = h

    ax.set_ylabel("% of total HLES")

    ax.xaxis.set_major_formatter(FuncFormatter(func=format_month_label))
    ax.xaxis.set_major_locator(
        MonthLocator(bymonthday=int(sum(width[:len(label_to_series)]) / 2.) +
                     1))
    ax.spines['right'].set_visible(False)
    ax.spines['top'].set_visible(False)
    # ax.set_title(common_params.varname_to_display_name[varname])
    ax.yaxis.grid(True, linestyle="--", linewidth=0.5)
    ax.text(1,
            1,
            "(a)",
            fontdict=dict(weight="bold"),
            transform=ax.transAxes,
            va="top",
            ha="right")
    ax_with_legend = ax

    # area average annual total HLES
    text_align_props = dict(transform=ax.transAxes, va="bottom", ha="right")

    cur_hles_annual = label_to_annual_hles[common_params.crcm_nemo_cur_label]
    fut_hles_annual = label_to_annual_hles[common_params.crcm_nemo_fut_label]

    ax.text(
        1,
        0.2,
        r"$\Delta_{\rm total}$" +
        f"({(fut_hles_annual - cur_hles_annual) / cur_hles_annual * 100:.1f}%)",
        **text_align_props,
        fontdict=dict(size=6))

    print(width[:len(label_to_series)])

    # plot HLES amount changes for each month
    ax = fig.add_subplot(gs[0, 1], sharex=ax)
    cur_data = label_to_series[common_params.crcm_nemo_cur_label]
    fut_data = label_to_series[common_params.crcm_nemo_fut_label]

    perc_change = (fut_data - cur_data) / cur_data * 100.0
    perc_change_sel = [perc_change[d.month] for d in dates]
    h = ax.bar(dates_num + width,
               perc_change_sel,
               edgecolor="k",
               linewidth=0.5,
               facecolor="orange",
               width=10,
               align="center",
               zorder=10)
    label_to_handle[r"CRCM5_NEMO(f-c)"] = h
    ax.set_ylabel("% of current HLES")
    ax.spines['right'].set_visible(False)
    ax.spines['top'].set_visible(False)
    ax.yaxis.grid(True, linestyle="--", linewidth=0.5)
    ax.text(1,
            1,
            "(b)",
            fontdict=dict(weight="bold"),
            transform=ax.transAxes,
            va="top",
            ha="right")

    # Add a common legend
    labels = list(label_to_handle)
    handles = [label_to_handle[l] for l in labels]
    ax_with_legend.legend(handles,
                          labels,
                          bbox_to_anchor=(0, -0.18),
                          loc="upper left",
                          borderaxespad=0.,
                          ncol=1)

    # ax.grid()
    sel_months_str = "_".join([str(m) for m in selected_months])

    common_params.img_folder.mkdir(exist_ok=True)
    img_file = common_params.img_folder / f"{varname}_histo_cc_m{sel_months_str}_HL.png"
    print(f"Saving plot to {img_file}")
    fig.savefig(img_file, **common_params.image_file_options)
def main(varname=""):
    plot_utils.apply_plot_params(width_cm=22, height_cm=5, font_size=8)
    # series = get_monthly_accumulations_area_avg(data_dir="/HOME/huziy/skynet3_rech1/Netbeans Projects/Python/RPN/lake_effect_analysis_Obs_monthly_1980-2009",
    #                                             varname=varname)

    # series = get_monthly_accumulations_area_avg(data_dir="/RESCUE/skynet3_rech1/huziy/Netbeans Projects/Python/RPN/lake_effect_analysis_CRCM5_NEMO_1980-2009_monthly",
    #                                             varname=varname)

    # series = get_monthly_accumulations_area_avg(data_dir="/RESCUE/skynet3_rech1/huziy/Netbeans Projects/Python/RPN/lake_effect_analysis_CRCM5_HL_1980-2009_monthly",
    #                                             varname=varname)

    hles_bin_edges = np.arange(0.1, 0.34, 0.02)

    # selected_months = [10, 11, 12, 1, 2, 3, 4, 5]
    selected_seasons = OrderedDict([("ND", [11, 12]), ("JF", [1, 2]),
                                    ("MA", [3, 4]),
                                    ("NDJFMA", [11, 12, 1, 2, 3, 4])])

    data_root = common_params.data_root

    label_to_datapath = OrderedDict([
        # ("Obs", "/HOME/huziy/skynet3_rech1/Netbeans Projects/Python/RPN/lake_effect_analysis_Obs_monthly_1980-2009"),
        # ("Obs", "/HOME/huziy/skynet3_rech1/Netbeans Projects/Python/RPN/lake_effect_analysis_daily_Obs_monthly_icefix_1980-2009"),
        # (common_params.crcm_nemo_cur_label, data_root / "lake_effect_analysis_CRCM5_NEMO_CanESM2_RCP85_1989-2010_1989-2010" / "merged"),
        # (common_params.crcm_nemo_fut_label, data_root / "lake_effect_analysis_CRCM5_NEMO_CanESM2_RCP85_2079-2100_2079-2100" / "merged"),
        (common_params.crcm_nemo_cur_label, data_root /
         "lake_effect_analysis_CRCM5_NEMO_fix_CanESM2_RCP85_1989-2010_monthly_1989-2010"
         / "merged"),
        (common_params.crcm_nemo_fut_label, data_root /
         "lake_effect_analysis_CRCM5_NEMO_fix_CanESM2_RCP85_2079-2100_monthly_2079-2100"
         / "merged"),
    ])

    # longutudes and latitudes of the focus region around the Great Lakes (we define it, mostly for performance
    # issues and to eliminate regions with 0 hles that still are in the 200 km HLES zone)
    focus_region_lonlat_nc_file = data_root / "lon_lat.nc"

    label_to_series = OrderedDict()
    label_to_color = {
        common_params.crcm_nemo_cur_label: "skyblue",
        common_params.crcm_nemo_fut_label: "salmon"
    }

    gl_mask = get_gl_mask(label_to_datapath[common_params.crcm_nemo_cur_label])
    hles_region_mask = get_mask_of_points_near_lakes(gl_mask,
                                                     npoints_radius=20)

    # select a file from the directory
    sel_file = None
    for f in label_to_datapath[common_params.crcm_nemo_cur_label].iterdir():
        if f.is_file():
            sel_file = f
            break

    assert sel_file is not None, f"Could not find any files in {label_to_datapath[common_params.crcm_nemo_cur_label]}"

    # Take into account the focus region
    with xarray.open_dataset(sel_file) as ds:
        hles_region_mask_lons, hles_region_mask_lats = [
            ds[k].values for k in ["lon", "lat"]
        ]

        with xarray.open_dataset(focus_region_lonlat_nc_file) as ds_focus:
            focus_lons, focus_lats = [
                ds_focus[k].values for k in ["lon", "lat"]
            ]

        coords_src = lat_lon.lon_lat_to_cartesian(
            hles_region_mask_lons.flatten(), hles_region_mask_lats.flatten())
        coords_dst = lat_lon.lon_lat_to_cartesian(focus_lons.flatten(),
                                                  focus_lats.flatten())

        ktree = KDTree(list(zip(*coords_src)))

        dists, inds = ktree.query(list(zip(*coords_dst)), k=1)

        focus_mask = hles_region_mask.flatten()
        focus_mask[...] = False
        focus_mask[inds] = True
        focus_mask.shape = hles_region_mask.shape

    for seas_name, selected_months in selected_seasons.items():
        # read and calculate
        for label, datapath in label_to_datapath.items():
            hles_file = None

            # select hles file in the folder
            for f in datapath.iterdir():
                if f.name.endswith("_daily.nc"):
                    hles_file = f
                    break

            assert hles_file is not None, f"Could not find any HLES files in {datapath}"

            series = get_hles_amount_distribution_from_merged(
                data_file=hles_file,
                varname=varname,
                region_of_interest_mask=hles_region_mask & focus_mask,
                selected_months=selected_months,
                bin_edges=hles_bin_edges)
            label_to_series[label] = series

        #  plotting
        gs = GridSpec(1, 1, wspace=0.05)

        fig = plt.figure()
        ax = fig.add_subplot(gs[0, 0])

        # calculate bar widths
        widths = np.diff(hles_bin_edges)

        label_to_handle = OrderedDict()

        for i, (label, series) in enumerate(label_to_series.items()):
            values = series.values if hasattr(series, "values") else series

            # values = values / values.sum() * 100

            logger.debug([label, values])
            logger.debug(f"sum(values) = {sum(values)}")

            # h = ax.bar(hles_bin_edges[:-1] + i * widths / len(label_to_series), values, width=widths / len(label_to_series),
            #            align="edge", linewidth=0.5,
            #            edgecolor="k",
            #            facecolor=label_to_color[label], label=label, zorder=10)

            h = ax.plot(hles_bin_edges[:-1],
                        values,
                        color=label_to_color[label],
                        marker="o",
                        label=label,
                        markersize=2.5)
            # label_to_handle[label] = h

        ax.set_xlabel("HLES (m)")
        ax.set_title(f"HLES distribution, {seas_name}")

        ax.spines['right'].set_visible(False)
        ax.spines['top'].set_visible(False)
        # ax.set_title(common_params.varname_to_display_name[varname])
        ax.yaxis.grid(True, linestyle="--", linewidth=0.5)
        # ax.text(1, 1, "(a)", fontdict=dict(weight="bold"), transform=ax.transAxes, va="top", ha="right")
        ax_with_legend = ax
        ax.set_xlim((0.1, None))

        # area average annual total HLES
        text_align_props = dict(transform=ax.transAxes,
                                va="bottom",
                                ha="right")

        # Plot the domain and the HLES region of interest
        # ax = fig.add_subplot(gs[0, 0])
        # topo_nc_file = data_root / "geophys_452x260_me.nc"
        # ax = plot_domain_and_interest_region(ax, topo_nc_file, focus_region_lonlat_nc_file=focus_region_lonlat_nc_file)
        # ax.set_title("(a) Experimental domain")
        #
        # # Add a common legend
        labels = list(label_to_handle)
        handles = [label_to_handle[l] for l in labels]
        ax_with_legend.legend(bbox_to_anchor=(0, -0.18),
                              loc="upper left",
                              borderaxespad=0.,
                              ncol=2)

        # ax.grid()
        sel_months_str = "_".join([str(m) for m in selected_months])

        common_params.img_folder.mkdir(exist_ok=True)
        img_file = common_params.img_folder / f"{varname}_histo_amount_cc_m{sel_months_str}_domain.png"
        print(f"Saving plot to {img_file}")
        fig.savefig(img_file, **common_params.image_file_options)
def plot_domain_and_interest_region(ax: Axes,
                                    topo_nc_file_path: Path,
                                    focus_region_lonlat_nc_file: Path = None):
    """
    :param focus_region_lonlat_nc_file: Path to the file containing focus region lons and lats
    :param region_mask_lats: latitudes corresponding to the region mask
    :param region_mask_lons:
    :param ax:
    :param topo_nc_file_path:
    :param region_mask:

    Note: below is the expected structure of the input netcdf file

    $ ncdump -h geophys_452x260_me.nc
    netcdf geophys_452x260_me {
    dimensions:
        x = 452 ;
        y = 260 ;
    variables:
        float ME(x, y) ;
        float lon(x, y) ;
        float lat(x, y) ;
        int proj_params ;
            proj_params:grid_type = "E" ;
            proj_params:lat1 = 0. ;
            proj_params:lon1 = 180. ;
            proj_params:lat2 = 1. ;
            proj_params:lon2 = 276. ;
    }
    """

    # read the model topography from the file
    with xarray.open_dataset(topo_nc_file_path) as topo_ds:
        topo_lons, topo_lats, topo = [
            topo_ds[k].values for k in ["lon", "lat", "ME"]
        ]

        prj_params = topo_ds["proj_params"]

        rll = RotatedLatLon(lon1=prj_params.lon1,
                            lat1=prj_params.lat1,
                            lon2=prj_params.lon2,
                            lat2=prj_params.lat2)

        rot_pole_cpy = rll.get_cartopy_projection_obj()

    ax.set_visible(False)
    ax = ax.figure.add_axes(ax.get_position().bounds, projection=rot_pole_cpy)
    # ax.coastlines()

    gl_mask = get_gl_mask(topo_nc_file_path)
    region_mask = get_mask_of_points_near_lakes(gl_mask, npoints_radius=20)
    topo_lons[topo_lons > 180] -= 360

    xll, yll = rot_pole_cpy.transform_point(topo_lons[0, 0], topo_lats[0, 0],
                                            cartopy.crs.PlateCarree())
    xur, yur = rot_pole_cpy.transform_point(topo_lons[-1, -1], topo_lats[-1,
                                                                         -1],
                                            cartopy.crs.PlateCarree())
    map_extent = [xll, xur, yll, yur]
    print("Map extent: ", map_extent)

    topo_clevs = [0, 100, 200, 300, 400, 500, 600, 800, 1000, 1200]
    # bn = BoundaryNorm(topo_clevs, len(topo_clevs) - 1)
    cmap = cm.get_cmap("terrain")
    ocean_color = cmap(0.18)
    cmap, norm = colors.from_levels_and_colors(
        topo_clevs, cmap(np.linspace(0.3, 1,
                                     len(topo_clevs) - 1)))

    xyz_coords = rot_pole_cpy.transform_points(cartopy.crs.PlateCarree(),
                                               topo_lons, topo_lats)
    xx = xyz_coords[:, :, 0]
    yy = xyz_coords[:, :, 1]

    add_rectangle(ax,
                  xx,
                  yy,
                  margin=20,
                  edge_style="solid",
                  zorder=10,
                  linewidth=0.5)
    add_rectangle(ax,
                  xx,
                  yy,
                  margin=10,
                  edge_style="dashed",
                  zorder=10,
                  linewidth=0.5)

    # plot a rectangle for the focus region
    if focus_region_lonlat_nc_file is not None:
        with xarray.open_dataset(focus_region_lonlat_nc_file) as fr:
            focus_lons, focus_lats = fr["lon"].data, fr["lat"].data

            xyz_coords = rot_pole_cpy.transform_points(
                cartopy.crs.PlateCarree(), focus_lons, focus_lats)
            xxf, yyf = xyz_coords[..., 0], xyz_coords[..., 1]

            add_rectangle(ax,
                          xxf,
                          yyf,
                          edge_style="solid",
                          margin=0,
                          edgecolor="magenta",
                          zorder=10,
                          linewidth=1)

    cs = ax.pcolormesh(topo_lons[:, :],
                       topo_lats[:, :],
                       topo[:, :],
                       transform=cartopy.crs.PlateCarree(),
                       cmap=cmap,
                       norm=norm)

    to_plot = np.ma.masked_where(region_mask < 0.5, region_mask)
    ax.scatter(topo_lons,
               topo_lats,
               to_plot * 0.01,
               c="cyan",
               transform=cartopy.crs.PlateCarree(),
               alpha=0.5)

    # Add geographic features
    line_color = "k"
    ax.add_feature(common_params.LAKES_50m,
                   facecolor=cartopy.feature.COLORS["water"],
                   edgecolor=line_color,
                   linewidth=0.5)
    ax.add_feature(common_params.OCEAN_50m,
                   facecolor=cartopy.feature.COLORS["water"],
                   edgecolor=line_color,
                   linewidth=0.5)
    ax.add_feature(common_params.COASTLINE_50m,
                   facecolor="none",
                   edgecolor=line_color,
                   linewidth=0.5)
    ax.add_feature(common_params.RIVERS_50m,
                   facecolor="none",
                   edgecolor=line_color,
                   linewidth=0.5)
    ax.set_extent(map_extent, crs=rot_pole_cpy)

    # improve colorbar
    divider = make_axes_locatable(ax)
    ax_cb = divider.new_vertical(size="5%",
                                 pad=0.1,
                                 axes_class=plt.Axes,
                                 pack_start=True)
    ax.figure.add_axes(ax_cb)
    cb = plt.colorbar(cs, cax=ax_cb, orientation="horizontal")
    cb.ax.set_xticklabels(topo_clevs, rotation=45)
    return ax
def main(varname=""):
    plot_utils.apply_plot_params(width_cm=22, height_cm=5, font_size=8)
    # series = get_monthly_accumulations_area_avg(data_dir="/HOME/huziy/skynet3_rech1/Netbeans Projects/Python/RPN/lake_effect_analysis_Obs_monthly_1980-2009",
    #                                             varname=varname)

    # series = get_monthly_accumulations_area_avg(data_dir="/RESCUE/skynet3_rech1/huziy/Netbeans Projects/Python/RPN/lake_effect_analysis_CRCM5_NEMO_1980-2009_monthly",
    #                                             varname=varname)

    # series = get_monthly_accumulations_area_avg(data_dir="/RESCUE/skynet3_rech1/huziy/Netbeans Projects/Python/RPN/lake_effect_analysis_CRCM5_HL_1980-2009_monthly",
    #                                             varname=varname)

    selected_months = [10, 11, 12, 1, 2, 3, 4, 5]

    data_root = common_params.data_root

    label_to_datapath = OrderedDict([
        # ("Obs", "/HOME/huziy/skynet3_rech1/Netbeans Projects/Python/RPN/lake_effect_analysis_Obs_monthly_1980-2009"),
        # ("Obs", "/HOME/huziy/skynet3_rech1/Netbeans Projects/Python/RPN/lake_effect_analysis_daily_Obs_monthly_icefix_1980-2009"),
        # (common_params.crcm_nemo_cur_label, data_root / "lake_effect_analysis_CRCM5_NEMO_CanESM2_RCP85_1989-2010_1989-2010" / "merged"),
        # (common_params.crcm_nemo_fut_label, data_root / "lake_effect_analysis_CRCM5_NEMO_CanESM2_RCP85_2079-2100_2079-2100" / "merged"),
        (common_params.crcm_nemo_cur_label, data_root /
         "lake_effect_analysis_CRCM5_NEMO_fix_CanESM2_RCP85_1989-2010_monthly_1989-2010"
         / "merged"),
        (common_params.crcm_nemo_fut_label, data_root /
         "lake_effect_analysis_CRCM5_NEMO_fix_CanESM2_RCP85_2079-2100_monthly_2079-2100"
         / "merged"),
    ])

    # longutudes and latitudes of the focus region around the Great Lakes (we define it, mostly for performance
    # issues and to eliminate regions with 0 hles that still are in the 200 km HLES zone)
    focus_region_lonlat_nc_file = data_root / "lon_lat.nc"

    label_to_series = OrderedDict()
    label_to_color = {
        common_params.crcm_nemo_cur_label: "skyblue",
        common_params.crcm_nemo_fut_label: "salmon"
    }

    gl_mask = get_gl_mask(label_to_datapath[common_params.crcm_nemo_cur_label])
    hles_region_mask = get_mask_of_points_near_lakes(gl_mask,
                                                     npoints_radius=20)

    # select a file from the directory
    sel_file = None
    for f in label_to_datapath[common_params.crcm_nemo_cur_label].iterdir():
        if f.is_file():
            sel_file = f
            break

    assert sel_file is not None, f"Could not find any files in {label_to_datapath[common_params.crcm_nemo_cur_label]}"

    # Take into account the focus region
    with xarray.open_dataset(sel_file) as ds:
        hles_region_mask_lons, hles_region_mask_lats = [
            ds[k].values for k in ["lon", "lat"]
        ]

        with xarray.open_dataset(focus_region_lonlat_nc_file) as ds_focus:
            focus_lons, focus_lats = [
                ds_focus[k].values for k in ["lon", "lat"]
            ]

        coords_src = lat_lon.lon_lat_to_cartesian(
            hles_region_mask_lons.flatten(), hles_region_mask_lats.flatten())
        coords_dst = lat_lon.lon_lat_to_cartesian(focus_lons.flatten(),
                                                  focus_lats.flatten())

        ktree = KDTree(list(zip(*coords_src)))

        dists, inds = ktree.query(list(zip(*coords_dst)), k=1)

        focus_mask = hles_region_mask.flatten()
        focus_mask[...] = False
        focus_mask[inds] = True
        focus_mask.shape = hles_region_mask.shape

    for label, datapath in label_to_datapath.items():
        hles_file = None
        for f in datapath.iterdir():
            if f.name.endswith("_daily.nc"):
                hles_file = f
                break

        assert hles_file is not None, f"Could not find any HLES files in {datapath}"

        series = get_monthly_accumulations_area_avg_from_merged(
            data_file=hles_file,
            varname=varname,
            region_of_interest_mask=hles_region_mask & focus_mask)
        label_to_series[label] = series

    #  plotting
    gs = GridSpec(1, 2, wspace=0.05)

    fig = plt.figure()
    ax = fig.add_subplot(gs[0, 1])

    start_date = datetime(2001, 10, 1)

    dates = [
        start_date.replace(month=(start_date.month + i) % 13 +
                           int((start_date.month + i) % 13 == 0),
                           year=start_date.year + (start_date.month + i) // 13)
        for i in range(13)
    ]

    def format_month_label(x, pos):
        logging.debug(num2date(x))
        return "{:%b}".format(num2date(x))

    # calculate bar widths
    dates_num = date2num(dates)
    width = np.diff(dates_num) / (len(label_to_series) * 1.5)
    width = np.array([width[0] for _ in width])

    # select the months
    width = np.array(
        [w for w, d in zip(width, dates) if d.month in selected_months])
    dates = [d for d in dates[:-1] if d.month in selected_months]
    dates_num = date2num(dates)

    label_to_handle = OrderedDict()

    label_to_annual_hles = OrderedDict()

    for i, (label, series) in enumerate(label_to_series.items()):
        values = [series[d.month] * 100 for d in dates]

        # convert to percentages
        values_sum = sum(values)

        # save the total annual hles for later reuse
        label_to_annual_hles[label] = values_sum

        # values = [v / values_sum * 100 for v in values]

        logger.debug([label, values])
        logger.debug(f"sum(values) = {sum(values)}")

        h = ax.bar(dates_num + i * width,
                   values,
                   width=width,
                   align="edge",
                   linewidth=0.5,
                   edgecolor="k",
                   facecolor=label_to_color[label],
                   label=label,
                   zorder=10)
        label_to_handle[label] = h

    ax.set_ylabel("HLES (cm/day)")
    ax.set_title("(b) Monthly HLES distribution")

    ax.xaxis.set_major_formatter(FuncFormatter(func=format_month_label))
    ax.xaxis.set_major_locator(
        MonthLocator(bymonthday=int(sum(width[:len(label_to_series)]) / 2.) +
                     1))
    ax.spines['right'].set_visible(False)
    ax.spines['top'].set_visible(False)
    # ax.set_title(common_params.varname_to_display_name[varname])
    ax.yaxis.grid(True, linestyle="--", linewidth=0.5)
    # ax.text(1, 1, "(a)", fontdict=dict(weight="bold"), transform=ax.transAxes, va="top", ha="right")
    ax_with_legend = ax

    # area average annual total HLES
    text_align_props = dict(transform=ax.transAxes, va="bottom", ha="right")

    cur_hles_annual = label_to_annual_hles[common_params.crcm_nemo_cur_label]
    fut_hles_annual = label_to_annual_hles[common_params.crcm_nemo_fut_label]

    ax.text(
        1,
        0.2,
        r"$\Delta_{\rm total}$" +
        f"({(fut_hles_annual - cur_hles_annual) / cur_hles_annual * 100:.1f}%)",
        **text_align_props,
        fontdict=dict(size=6))

    # Plot the domain and the HLES region of interest
    ax = fig.add_subplot(gs[0, 0])
    topo_nc_file = data_root / "geophys_452x260_me.nc"
    ax = plot_domain_and_interest_region(
        ax,
        topo_nc_file,
        focus_region_lonlat_nc_file=focus_region_lonlat_nc_file)
    ax.set_title("(a) Experimental domain")

    # Add a common legend
    labels = list(label_to_handle)
    handles = [label_to_handle[l] for l in labels]
    ax_with_legend.legend(handles,
                          labels,
                          bbox_to_anchor=(0, -0.18),
                          loc="upper left",
                          borderaxespad=0.,
                          ncol=2)

    # ax.grid()
    sel_months_str = "_".join([str(m) for m in selected_months])

    common_params.img_folder.mkdir(exist_ok=True)
    img_file = common_params.img_folder / f"{varname}_histo_cc_m{sel_months_str}_domain.png"
    print(f"Saving plot to {img_file}")
    fig.savefig(img_file, **common_params.image_file_options)