Exemplo n.º 1
0
def main():
    # Define the simulations to be validated
    r_config = RunConfig(
        data_path=
        "/RESCUE/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-hcd-r.hdf5",
        start_year=1990,
        end_year=2010,
        label="CRCM5-L1")
    r_config_list = [r_config]

    r_config = RunConfig(
        data_path=
        "/RESCUE/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-r.hdf5",
        start_year=1990,
        end_year=2010,
        label="CRCM5-NL")
    r_config_list.append(r_config)

    bmp_info = analysis.get_basemap_info_from_hdf(file_path=r_config.data_path)
    bmp_info.should_draw_grey_map_background = True
    bmp_info.should_draw_basin_boundaries = False
    bmp_info.map_bg_color = "0.75"

    station_ids = ["104001", "093806", "093801", "081002", "081007", "080718"]

    # get river network information used in the model
    flow_directions = analysis.get_array_from_file(
        r_config.data_path, var_name=infovar.HDF_FLOW_DIRECTIONS_NAME)
    accumulation_area_km2 = analysis.get_array_from_file(
        path=r_config.data_path, var_name=infovar.HDF_ACCUMULATION_AREA_NAME)
    cell_manager = CellManager(flow_dirs=flow_directions,
                               lons2d=bmp_info.lons,
                               lats2d=bmp_info.lats,
                               accumulation_area_km2=accumulation_area_km2)

    # Get the list of stations to indicate on the bias map
    stations = cehq_station.read_station_data(start_date=None,
                                              end_date=None,
                                              selected_ids=station_ids)
    """:type : list[Station]"""

    xx, yy = bmp_info.get_proj_xy()
    station_to_modelpoint = cell_manager.get_model_points_for_stations(
        station_list=stations)
    upstream_edges = cell_manager.get_upstream_polygons_for_points(
        model_point_list=station_to_modelpoint.values(), xx=xx, yy=yy)

    bmp_info.draw_colorbar_for_each_subplot = True

    # Validate temperature, precip and swe
    obs_path_anusplin = "/home/huziy/skynet3_rech1/anusplin_links"
    obs_path_swe = "data/swe_ross_brown/swe.nc"
    model_var_to_obs_path = OrderedDict([("TT", obs_path_anusplin),
                                         ("I5", obs_path_swe)])

    model_var_to_season = OrderedDict([
        ("TT", OrderedDict([("Spring", range(3, 6))])),
        ("I5", OrderedDict([("Winter", [1, 2, 12])]))
    ])

    vname_to_obs_data = {}

    # parameters that won't change in the loop over variable names
    params_const = dict(rconfig=r_config, bmp_info=bmp_info)

    for vname, obs_path in model_var_to_obs_path.items():
        season_to_obs_data = get_seasonal_clim_obs_data(
            vname=vname,
            obs_path=obs_path,
            season_to_months=model_var_to_season[vname],
            **params_const)

        # Comment swe over lakes, since I5 calculated only for land
        if vname in [
                "I5",
        ]:
            for season in season_to_obs_data:
                season_to_obs_data[season] = maskoceans(
                    bmp_info.lons,
                    bmp_info.lats,
                    season_to_obs_data[season],
                    inlands=True)

        vname_to_obs_data[vname] = season_to_obs_data

    # Plotting
    plot_all_vars_in_one_fig = True

    fig = None
    gs = None
    if plot_all_vars_in_one_fig:
        plot_utils.apply_plot_params(font_size=12,
                                     width_pt=None,
                                     width_cm=25,
                                     height_cm=20)
        fig = plt.figure()
        ncols = len(model_var_to_obs_path) + 1
        gs = GridSpec(len(r_config_list),
                      ncols,
                      width_ratios=(ncols - 1) * [
                          1.,
                      ] + [
                          0.05,
                      ])
    else:
        plot_utils.apply_plot_params(font_size=12,
                                     width_pt=None,
                                     width_cm=25,
                                     height_cm=25)

    station_x_list = []
    station_y_list = []

    mvarname_to_cs = {}
    for row, r_config in enumerate(r_config_list):
        for col, mname in enumerate(model_var_to_obs_path):

            row_axes = [
                fig.add_subplot(gs[row, col]),
            ]

            mvarname_to_cs[mname] = compare_vars(
                vname_model=mname,
                vname_to_obs=vname_to_obs_data,
                r_config=r_config,
                season_to_months=model_var_to_season[mname],
                bmp_info_agg=bmp_info,
                axes_list=row_axes)

            # -1 in order to exclude colorbars
            for the_ax in row_axes:

                the_ax.set_title(the_ax.get_title() + ", {}".format(
                    infovar.get_long_display_label_for_var(mname)))
                # Need titles only for the first row
                if row > 0:
                    the_ax.set_title("")

                if col == 0:
                    the_ax.set_ylabel(r_config.label)
                else:
                    the_ax.set_ylabel("")

                draw_upstream_area_bounds(the_ax, upstream_edges, color="g")

                if len(station_x_list) == 0:
                    for the_station in stations:
                        xst, yst = bmp_info.basemap(the_station.longitude,
                                                    the_station.latitude)
                        station_x_list.append(xst)
                        station_y_list.append(yst)

                bmp_info.basemap.scatter(station_x_list,
                                         station_y_list,
                                         c="g",
                                         ax=the_ax,
                                         s=20,
                                         zorder=10,
                                         alpha=0.5)

    # Save the figure if necessary
    if plot_all_vars_in_one_fig:

        if not img_folder.is_dir():
            img_folder.mkdir(parents=True)

        fig_path = img_folder.joinpath("{}.png".format(
            "_".join(model_var_to_obs_path)))
        with fig_path.open("wb") as figfile:
            fig.savefig(figfile, format="png", bbox_inches="tight")

        plt.close(fig)
def main():
    season_to_months = DEFAULT_SEASON_TO_MONTHS

    r_config = RunConfig(
        data_path="/RESCUE/skynet3_rech1/huziy/hdf_store/quebec_0.1_crcm5-hcd-r.hdf5",
        start_year=1990, end_year=2010, label="CRCM5-L"
    )

    bmp_info = analysis.get_basemap_info_from_hdf(file_path=r_config.data_path)
    bmp_info.should_draw_grey_map_background = True
    bmp_info.should_draw_basin_boundaries = False
    bmp_info.map_bg_color = "0.75"

    station_ids = [
        "104001", "093806", "093801", "081002", "081007", "080718"
    ]

    # get river network information used in the model
    flow_directions = analysis.get_array_from_file(r_config.data_path, var_name=infovar.HDF_FLOW_DIRECTIONS_NAME)
    accumulation_area_km2 = analysis.get_array_from_file(path=r_config.data_path,
                                                         var_name=infovar.HDF_ACCUMULATION_AREA_NAME)
    cell_manager = CellManager(flow_dirs=flow_directions,
                               lons2d=bmp_info.lons,
                               lats2d=bmp_info.lats, accumulation_area_km2=accumulation_area_km2)

    # Get the list of stations to indicate on the bias map
    stations = cehq_station.read_station_data(
        start_date=None, end_date=None, selected_ids=station_ids
    )
    """:type : list[Station]"""

    xx, yy = bmp_info.get_proj_xy()
    station_to_modelpoint = cell_manager.get_model_points_for_stations(station_list=stations)
    upstream_edges = cell_manager.get_upstream_polygons_for_points(
        model_point_list=station_to_modelpoint.values(), xx=xx, yy=yy)


    # Validate temperature, precip and swe
    obs_path_anusplin = "/home/huziy/skynet3_rech1/anusplin_links"
    obs_path_swe = "data/swe_ross_brown/swe.nc"
    model_var_to_obs_path = OrderedDict([
        ("TT", obs_path_anusplin),
    #    ("PR", obs_path_anusplin),
        ("I5", obs_path_swe)
    ])



    vname_to_obs_data = {}

    # parameters that won't change in the loop over variable names
    params_const = dict(rconfig=r_config, bmp_info=bmp_info, season_to_months=season_to_months)

    for vname, obs_path in model_var_to_obs_path.items():
        season_to_obs_data = get_seasonal_clim_obs_data(vname=vname, obs_path=obs_path, **params_const)

        # Comment swe over lakes, since I5 calculated only for land
        if vname in ["I5", ]:
            for season in season_to_obs_data:
                season_to_obs_data[season] = maskoceans(bmp_info.lons, bmp_info.lats,
                                                        season_to_obs_data[season],
                                                        inlands=True)

        vname_to_obs_data[vname] = season_to_obs_data


    # Plotting
    plot_all_vars_in_one_fig = True

    fig = None
    gs = None
    row_axes = []
    ncols = None
    if plot_all_vars_in_one_fig:
        plot_utils.apply_plot_params(font_size=12, width_pt=None, width_cm=25, height_cm=20)
        fig = plt.figure()
        ncols = len(season_to_months) + 1
        gs = GridSpec(len(model_var_to_obs_path), ncols, width_ratios=(ncols - 1) * [1., ] + [0.05, ])
    else:
        plot_utils.apply_plot_params(font_size=12, width_pt=None, width_cm=25, height_cm=25)

    row = 0
    station_x_list = []
    station_y_list = []
    for mname in model_var_to_obs_path:

        if plot_all_vars_in_one_fig:
            row_axes = [fig.add_subplot(gs[row, col]) for col in range(ncols)]

        compare_vars(vname_model=mname, vname_to_obs=vname_to_obs_data,
                     r_config=r_config,
                     season_to_months=season_to_months,
                     bmp_info_agg=bmp_info,
                     axes_list=row_axes)

        # -1 in order to exclude colorbars
        for the_ax in row_axes[:-1]:

            # Need titles only for the first row
            if row > 0:
                the_ax.set_title("")

            draw_upstream_area_bounds(the_ax, upstream_edges)

            if len(station_x_list) == 0:
                for the_station in stations:
                    xst, yst = bmp_info.basemap(the_station.longitude, the_station.latitude)
                    station_x_list.append(xst)
                    station_y_list.append(yst)

            bmp_info.basemap.scatter(station_x_list, station_y_list, c="g", ax=the_ax, s=5, zorder=10, alpha=0.5)



        # Hide fall swe
        if mname in ["I5"]:
            row_axes[-2].set_visible(False)

        row += 1


    # Save the figure if necessary
    if plot_all_vars_in_one_fig:
        fig_path = img_folder.joinpath("{}.png".format("_".join(model_var_to_obs_path)))
        with fig_path.open("wb") as figfile:
            fig.savefig(figfile, format="png", bbox_inches="tight")

        plt.close(fig)
def plot_basin_outlets(shape_file=BASIN_BOUNDARIES_FILE,
                       bmp_info=None,
                       directions=None,
                       accumulation_areas=None,
                       lake_fraction_field=None):
    assert isinstance(bmp_info, BasemapInfo)

    driver = ogr.GetDriverByName("ESRI Shapefile")
    print(driver)
    ds = driver.Open(shape_file, 0)

    assert isinstance(ds, ogr.DataSource)
    layer = ds.GetLayer()

    assert isinstance(layer, ogr.Layer)
    print(layer.GetFeatureCount())

    latlong_proj = osr.SpatialReference()
    latlong_proj.ImportFromEPSG(4326)

    utm_proj = layer.GetSpatialRef()

    # create Coordinate Transformation
    coord_transform = osr.CoordinateTransformation(latlong_proj, utm_proj)

    utm_coords = coord_transform.TransformPoints(
        list(zip(bmp_info.lons.flatten(), bmp_info.lats.flatten())))
    utm_coords = np.asarray(utm_coords)
    x_utm = utm_coords[:, 0].reshape(bmp_info.lons.shape)
    y_utm = utm_coords[:, 1].reshape(bmp_info.lons.shape)

    basin_mask = np.zeros_like(bmp_info.lons)
    cell_manager = CellManager(directions,
                               accumulation_area_km2=accumulation_areas,
                               lons2d=bmp_info.lons,
                               lats2d=bmp_info.lats)

    index = 1
    basins = []
    basin_names = []
    basin_name_to_mask = {}
    for feature in layer:
        assert isinstance(feature, ogr.Feature)
        # print feature["FID"]

        geom = feature.GetGeometryRef()
        assert isinstance(geom, ogr.Geometry)

        basins.append(ogr.CreateGeometryFromWkb(geom.ExportToWkb()))
        basin_names.append(feature["abr"])

    accumulation_areas_temp = accumulation_areas.copy()
    lons_out, lats_out = [], []
    basin_names_out = []
    name_to_ij_out = OrderedDict()

    min_basin_area = min(b.GetArea() * 1.0e-6 for b in basins)

    while len(basins):
        fm = np.max(accumulation_areas_temp)

        i, j = np.where(fm == accumulation_areas_temp)
        i, j = i[0], j[0]
        p = ogr.CreateGeometryFromWkt("POINT ({} {})".format(
            x_utm[i, j], y_utm[i, j]))
        b_selected = None
        name_selected = None
        for name, b in zip(basin_names, basins):

            assert isinstance(b, ogr.Geometry)
            assert isinstance(p, ogr.Geometry)
            if b.Contains(p.Buffer(2000 * 2**0.5)):
                # Check if there is an upstream cell from the same basin
                the_mask = cell_manager.get_mask_of_upstream_cells_connected_with_by_indices(
                    i, j)

                # Save the mask of the basin for future use
                basin_name_to_mask[name] = the_mask

                # if is_part_of_points_in(b, x_utm[the_mask == 1], y_utm[the_mask == 1]):
                # continue

                b_selected = b
                name_selected = name
                # basin_names_out.append(name)

                lons_out.append(bmp_info.lons[i, j])
                lats_out.append(bmp_info.lats[i, j])
                name_to_ij_out[name] = (i, j)

                basin_mask[the_mask == 1] = index
                index += 1
                break

        if b_selected is not None:
            basins.remove(b_selected)
            basin_names.remove(name_selected)
            outlet_index_in_basin = 1
            current_basin_name = name_selected
            while current_basin_name in basin_names_out:
                current_basin_name = name_selected + str(outlet_index_in_basin)
                outlet_index_in_basin += 1

            basin_names_out.append(current_basin_name)
            print(len(basins), basin_names_out)

        accumulation_areas_temp[i, j] = -1

    plot_utils.apply_plot_params(font_size=12,
                                 width_pt=None,
                                 width_cm=20,
                                 height_cm=20)
    gs = GridSpec(2, 2, width_ratios=[1.0, 0.5], wspace=0.01)
    fig = plt.figure()

    ax = fig.add_subplot(gs[1, 0])
    xx, yy = bmp_info.get_proj_xy()
    bmp_info.basemap.drawcoastlines(linewidth=0.5, ax=ax)
    bmp_info.basemap.drawrivers(zorder=5, color="0.5", ax=ax)

    upstream_edges = cell_manager.get_upstream_polygons_for_points(
        model_point_list=[
            ModelPoint(ix=i, jy=j) for (i, j) in name_to_ij_out.values()
        ],
        xx=xx,
        yy=yy)

    upstream_edges_latlon = cell_manager.get_upstream_polygons_for_points(
        model_point_list=[
            ModelPoint(ix=i, jy=j) for (i, j) in name_to_ij_out.values()
        ],
        xx=bmp_info.lons,
        yy=bmp_info.lats)

    plot_utils.draw_upstream_area_bounds(ax,
                                         upstream_edges=upstream_edges,
                                         color="r",
                                         linewidth=0.6)
    plot_utils.save_to_shape_file(upstream_edges_latlon, in_proj=None)

    xs, ys = bmp_info.basemap(lons_out, lats_out)
    bmp_info.basemap.scatter(xs, ys, c="0.75", s=30, zorder=10)
    bmp_info.basemap.drawparallels(np.arange(-90, 90, 5),
                                   labels=[True, False, False, False],
                                   linewidth=0.5)

    bmp_info.basemap.drawmeridians(np.arange(-180, 180, 5),
                                   labels=[False, False, False, True],
                                   linewidth=0.5)

    cmap = cm.get_cmap("rainbow", index - 1)
    bn = BoundaryNorm(list(range(index + 1)), index - 1)

    # basin_mask = np.ma.masked_where(basin_mask < 0.5, basin_mask)
    # bmp_info.basemap.pcolormesh(xx, yy, basin_mask, norm=bn, cmap=cmap, ax=ax)

    xmin, xmax = ax.get_xlim()
    ymin, ymax = ax.get_ylim()

    print(xmin, xmax, ymin, ymax)
    dx = xmax - xmin
    dy = ymax - ymin
    step_y = 0.1
    step_x = 0.12
    y0_frac = 0.75
    y0_frac_bottom = 0.02
    x0_frac = 0.35
    bname_to_text_coords = {
        "RDO": (xmin + x0_frac * dx, ymin + y0_frac_bottom * dy),
        "STM": (xmin + (x0_frac + step_x) * dx, ymin + y0_frac_bottom * dy),
        "SAG":
        (xmin + (x0_frac + 2 * step_x) * dx, ymin + y0_frac_bottom * dy),
        "BOM":
        (xmin + (x0_frac + 3 * step_x) * dx, ymin + y0_frac_bottom * dy),
        "MAN":
        (xmin + (x0_frac + 4 * step_x) * dx, ymin + y0_frac_bottom * dy),
        "MOI":
        (xmin + (x0_frac + 5 * step_x) * dx, ymin + y0_frac_bottom * dy),
        "ROM": (xmin + (x0_frac + 5 * step_x) * dx,
                ymin + (y0_frac_bottom + step_y) * dy),
        "NAT": (xmin + (x0_frac + 5 * step_x) * dx,
                ymin + (y0_frac_bottom + 2 * step_y) * dy),

        ######
        "CHU": (xmin + (x0_frac + 5 * step_x) * dx, ymin + y0_frac * dy),
        "GEO": (xmin + (x0_frac + 5 * step_x) * dx,
                ymin + (y0_frac + step_y) * dy),
        "BAL": (xmin + (x0_frac + 5 * step_x) * dx,
                ymin + (y0_frac + 2 * step_y) * dy),
        "PYR": (xmin + (x0_frac + 4 * step_x) * dx,
                ymin + (y0_frac + 2 * step_y) * dy),
        "MEL": (xmin + (x0_frac + 3 * step_x) * dx,
                ymin + (y0_frac + 2 * step_y) * dy),
        "FEU": (xmin + (x0_frac + 2 * step_x) * dx,
                ymin + (y0_frac + 2 * step_y) * dy),
        "ARN": (xmin + (x0_frac + 1 * step_x) * dx,
                ymin + (y0_frac + 2 * step_y) * dy),

        ######
        "CAN": (xmin + 0.1 * dx, ymin + 0.80 * dy),
        "GRB": (xmin + 0.1 * dx, ymin + (0.80 - step_y) * dy),
        "LGR": (xmin + 0.1 * dx, ymin + (0.80 - 2 * step_y) * dy),
        "RUP": (xmin + 0.1 * dx, ymin + (0.80 - 3 * step_y) * dy),
        "WAS": (xmin + 0.1 * dx, ymin + (0.80 - 4 * step_y) * dy),
        "BEL": (xmin + 0.1 * dx, ymin + (0.80 - 5 * step_y) * dy),
    }

    # bmp_info.basemap.readshapefile(".".join(BASIN_BOUNDARIES_FILE.split(".")[:-1]).replace("utm18", "latlon"), "basin",
    #                                linewidth=1.2, ax=ax, zorder=9)

    for name, xa, ya, lona, lata in zip(basin_names_out, xs, ys, lons_out,
                                        lats_out):
        ax.annotate(name,
                    xy=(xa, ya),
                    xytext=bname_to_text_coords[name],
                    textcoords='data',
                    ha='right',
                    va='bottom',
                    bbox=dict(boxstyle='round,pad=0.4', fc='white'),
                    arrowprops=dict(arrowstyle='->',
                                    connectionstyle='arc3,rad=0',
                                    linewidth=0.25),
                    font_properties=FontProperties(size=8),
                    zorder=20)

        print(r"{} & {:.0f} \\".format(
            name, accumulation_areas[name_to_ij_out[name]]))

    # Plot zonally averaged lake fraction
    ax = fig.add_subplot(gs[1, 1])
    ydata = range(lake_fraction_field.shape[1])
    ax.plot(lake_fraction_field.mean(axis=0) * 100, ydata, lw=2)

    ax.fill_betweenx(ydata, lake_fraction_field.mean(axis=0) * 100, alpha=0.5)

    ax.set_xlabel("Lake fraction (%)")
    ax.set_ylim(min(ydata), max(ydata))
    ax.xaxis.set_tick_params(direction='out', width=1)
    ax.yaxis.set_tick_params(direction='out', width=1)
    ax.xaxis.set_ticks_position("bottom")
    ax.yaxis.set_ticks_position("none")

    ax.spines["top"].set_visible(False)
    ax.spines["right"].set_visible(False)

    for tl in ax.yaxis.get_ticklabels():
        tl.set_visible(False)

    # plot elevation, buffer zone, big lakes, grid cells
    ax = fig.add_subplot(gs[0, :])
    geophy_file = "/RESCUE/skynet3_rech1/huziy/from_guillimin/geophys_Quebec_0.1deg_260x260_with_dd_v6"

    r = RPN(geophy_file)
    elev = r.get_first_record_for_name("ME")
    lkfr = r.get_first_record_for_name("LKFR")
    fldr = r.get_first_record_for_name("FLDR")

    params = r.get_proj_parameters_for_the_last_read_rec()
    lons, lats = r.get_longitudes_and_latitudes_for_the_last_read_rec()
    rll = RotatedLatLon(**params)

    bsmp = rll.get_basemap_object_for_lons_lats(lons2d=lons,
                                                lats2d=lats,
                                                resolution="l")
    xx, yy = bsmp(lons, lats)

    dx = (xx[0, 0] - xx[-1, 0]) / xx.shape[0]
    dy = (yy[0, 0] - yy[0, -1]) / yy.shape[1]

    xx_ll_crnrs = xx - dx / 2
    yy_ll_crnrs = yy - dy / 2

    xx_ur_crnrs = xx + dx / 2
    yy_ur_crnrs = yy + dy / 2

    ll_lon, ll_lat = bsmp(xx_ll_crnrs[0, 0], yy_ll_crnrs[0, 0], inverse=True)
    ur_lon, ur_lat = bsmp(xx_ur_crnrs[-1, -1],
                          yy_ur_crnrs[-1, -1],
                          inverse=True)

    crnr_lons = np.array([[ll_lon, ll_lon], [ur_lon, ur_lon]])

    crnr_lats = np.array([[ll_lat, ll_lat], [ur_lat, ur_lat]])

    bsmp = rll.get_basemap_object_for_lons_lats(lons2d=crnr_lons,
                                                lats2d=crnr_lats)

    # plot elevation
    levs = [0, 100, 200, 300, 500, 700, 1000, 1500, 2000, 2800]
    norm = BoundaryNorm(levs, len(levs) - 1)
    the_cmap = my_colormaps.get_cmap_from_ncl_spec_file(
        path="colormap_files/OceanLakeLandSnow.rgb", ncolors=len(levs) - 1)

    lons[lons > 180] -= 360
    me_to_plot = maskoceans(lons, lats, elev, resolution="l")
    im = bsmp.contourf(xx,
                       yy,
                       me_to_plot,
                       cmap=the_cmap,
                       levels=levs,
                       norm=norm,
                       ax=ax)
    bsmp.colorbar(im)

    bsmp.drawcoastlines(linewidth=0.5, ax=ax)

    # show large lake points
    gl_lakes = np.ma.masked_where((lkfr < 0.6) | (fldr <= 0) | (fldr > 128),
                                  lkfr)
    gl_lakes[~gl_lakes.mask] = 1.0
    bsmp.pcolormesh(xx,
                    yy,
                    gl_lakes,
                    cmap=cm.get_cmap("Blues"),
                    ax=ax,
                    vmin=0,
                    vmax=1,
                    zorder=3)

    # show free zone border
    margin = 20
    x1 = xx_ll_crnrs[margin, margin]
    x2 = xx_ur_crnrs[-margin, margin]
    y1 = yy_ll_crnrs[margin, margin]
    y2 = yy_ur_crnrs[margin, -margin]
    pol_corners = ((x1, y1), (x2, y1), (x2, y2), (x1, y2))
    ax.add_patch(Polygon(xy=pol_corners, fc="none", ls="solid", lw=3,
                         zorder=5))

    # show blending zone border (with halo zone)
    margin = 10
    x1 = xx_ll_crnrs[margin, margin]
    x2 = xx_ur_crnrs[-margin, margin]
    y1 = yy_ll_crnrs[margin, margin]
    y2 = yy_ur_crnrs[margin, -margin]
    pol_corners = ((x1, y1), (x2, y1), (x2, y2), (x1, y2))
    ax.add_patch(
        Polygon(xy=pol_corners, fc="none", ls="dashed", lw=3, zorder=5))

    # show the grid
    step = 20
    xx_ll_crnrs_ext = np.zeros([n + 1 for n in xx_ll_crnrs.shape])
    yy_ll_crnrs_ext = np.zeros([n + 1 for n in yy_ll_crnrs.shape])

    xx_ll_crnrs_ext[:-1, :-1] = xx_ll_crnrs
    yy_ll_crnrs_ext[:-1, :-1] = yy_ll_crnrs
    xx_ll_crnrs_ext[:-1, -1] = xx_ll_crnrs[:, -1]
    yy_ll_crnrs_ext[-1, :-1] = yy_ll_crnrs[-1, :]

    xx_ll_crnrs_ext[-1, :] = xx_ur_crnrs[-1, -1]
    yy_ll_crnrs_ext[:, -1] = yy_ur_crnrs[-1, -1]

    bsmp.pcolormesh(xx_ll_crnrs_ext[::step, ::step],
                    yy_ll_crnrs_ext[::step, ::step],
                    np.ma.masked_all_like(xx_ll_crnrs_ext)[::step, ::step],
                    edgecolors="0.6",
                    ax=ax,
                    linewidth=0.05,
                    zorder=4,
                    alpha=0.5)

    ax.set_title("Elevation (m)")

    # plt.show()
    fig.savefig("qc_basin_outlets_points.png", bbox_inches="tight")
    # plt.show()
    plt.close(fig)

    return name_to_ij_out, basin_name_to_mask
def plot_station_positions(directions_file_path: Path, stations: list, ax: Axes, grid_config: GridConfig=default_domains.bc_mh_044,
                           save_upstream_boundaries_to_shp=False):


    with Dataset(str(directions_file_path)) as ds:
        flow_dirs = ds.variables["flow_direction_value"][:]
        flow_acc_area = ds.variables["accumulation_area"][:]
        lons_2d, lats_2d = [ds.variables[k][:] for k in ["lon", "lat"]]



    basemap, reg_of_interest = grid_config.get_basemap_using_shape_with_polygons_of_interest(lons_2d, lats_2d,
                                                                                             shp_path=default_domains.MH_BASINS_PATH,
                                                                                             resolution="i")


    cell_manager = CellManager(flow_dirs, lons2d=lons_2d, lats2d=lats_2d, accumulation_area_km2=flow_acc_area)
    station_to_model_point = cell_manager.get_model_points_for_stations(station_list=stations, nneighbours=8)

    #####
    xx, yy = basemap(lons_2d, lats_2d)
    upstream_edges = cell_manager.get_upstream_polygons_for_points(
        model_point_list=list(station_to_model_point.values()), xx=xx, yy=yy)

    upstream_edges_latlon = cell_manager.get_upstream_polygons_for_points(
        model_point_list=list(station_to_model_point.values()), xx=lons_2d, yy=lats_2d)




    plot_utils.draw_upstream_area_bounds(ax, upstream_edges=upstream_edges, color="r", linewidth=0.6)

    if save_upstream_boundaries_to_shp:
        plot_utils.save_to_shape_file(upstream_edges_latlon, folder_path="mh/engage_report/upstream_stations_areas/mh_{}".format(grid_config.dx), in_proj=None)


    basemap.drawrivers(linewidth=0.2)
    basemap.drawstates(linewidth=0.1)
    basemap.drawcountries(linewidth=0.1)
    basemap.drawcoastlines(linewidth=0.2)


    pos_ids, lons_pos, lats_pos = [], [], []
    pos_labels = []
    legend_lines = []
    for i, (s, mp) in enumerate(sorted(station_to_model_point.items(), key=lambda p: p[0].latitude, reverse=True), start=1):
        pos_ids.append(s.id)
        pos_labels.append(i)
        lons_pos.append(mp.longitude)
        lats_pos.append(mp.latitude)

        legend_lines.append("{}: {}".format(i, s.id))

    xm, ym = basemap(lons_pos, lats_pos)
    ax.scatter(xm, ym, c="g", s=20)
    for txt, x1, y1, pos_label in zip(pos_ids, xm, ym, pos_labels):
        ax.annotate(pos_label, xy=(x1, y1))



    at = AnchoredText("\n".join(legend_lines), prop=dict(size=8), frameon=True, loc=1)

    at.patch.set_boxstyle("round,pad=0.,rounding_size=0.2")
    ax.add_artist(at)