-
Julian Stürmer authoredJulian Stürmer authored
PlotPFC.jl 7.02 KiB
#* Functions that allow to compare different power flow solutions
#*------------------------------------------------------------------------------
#* NOTE: Utility functions used are defined in PlotUtils.jl
#*------------------------------------------------------------------------------
#=
Scatters branch loads contained in y_ndd versus branch loads in x_ndd. Possible plot settings can be seen in PlotUtils.jl.
=#
function scatter_branchloads(
x_ndd::Dict{String,<:Any},
y_ndd::Dict{String,<:Any},
settings::Dict{String,<:Any}; # plot settings
figpath = "" # where to save the figure
)
### Set plot settings
settings = _recursive_merge(
_default_settings(:scatter_branchloads), settings
)
### Get branch loadings from both network data dictionaries
x_bl_dict = Dict(
i => br[settings["x_pf_type"]] for (i, br) in x_ndd["branch"]
if br["br_status"] == 1
)
y_bl_dict = Dict(
i => br[settings["y_pf_type"]] for (i, br) in y_ndd["branch"]
if br["br_status"] == 1
)
# @assert length(x_bl_dict) == length(y_bl_dict) # same number of branches?
L = length(y_bl_dict)
# println(L)
x_bl, y_bl = zeros(L), zeros(L) # arrays for branch loads
### Write branch loads with correct ordering into arrays
for (n, key) in enumerate(keys(y_bl_dict))
x_bl[n] = x_bl_dict[key]
y_bl[n] = y_bl_dict[key]
end
### Plot straight lines with slope 1 as reference
x = [i for i in 0:0.01:1]
plt.plot(x, x, color="k", alpha=.7) # plot line with slope 1
### Scatter branch loads versus each other
diff = y_bl - x_bl # deviation from ratio 1 for coloring
diff[diff .== 0.0] .= -10 # map exact zero values to -10 for distinct color
# mcolors = pyimport("matplotlib.colors")
# offset = mcolors.TwoSlopeNorm(
# vcenter=0, vmin=minimum(diff), vmax=maximum(diff)
# ) # match diff to values between 0 and 1
cmap = plt.get_cmap(settings["cmap"])
cmap.set_under("tab:green")
sc = plt.scatter(
x_bl, y_bl,
s = settings["size"],
c = diff,
# c = offset(diff),
cmap = cmap,
vmin = -1.,
vmax = 1.,
edgecolors = settings["ec"],
linewidths = settings["lw"],
alpha = settings["alpha"]
)
### Add colorbar
sm = plt.cm.ScalarMappable(cmap=cmap, norm=plt.Normalize(-1., 1.))
# sm = plt.cm.ScalarMappable(cmap=cmap, offset)
cbar = plt.colorbar(sm)
cbar.ax.plot([-1, 1], [0.0, 0.0], "tab:green")
# cbar.add_lines(CS2)
cbar.ax.set_ylabel(
L"Difference $y-x$", rotation=-90, va="bottom"
)
### Plot labels
plt.xlabel(settings["xlabel"])
plt.ylabel(settings["ylabel"])
plt.savefig(figpath, bbox_inches="tight") # save figure
plt.close("all") # close figure
return nothing
end
#*------------------------------------------------------------------------------
#=
Plots a power grid similar to plot_pg in PlotPG.jl and colors the edges according to the difference in branch loads in ndd and ref_ndd. Possible plot settings can be seen in PlotUtils.jl.
=#
function plot_pg_pf_diff(
ndd::Dict{String,<:Any}, # NDD with (new) power flow
ref_ndd::Dict{String,<:Any}, # NDD with reference power flow
settings = Dict{String,Any}(); # plot settings
figpath = "" # where to save the figure
)
### Setup figure
figure::Figure, ax::PyObject = plt.subplots()::Tuple{Figure,PyObject}
w::Float64, h::Float64 = plt.figaspect(2/3)::Vector{Float64}
figure.set_size_inches(1.5w, 1.5h)
ax.set_aspect("equal")
### Set plot settings and plot power grid
settings = _recursive_merge(_default_settings(:plot_pg_pf_diff), settings)
_plot_pg_pf_diff!(ax, ndd, ref_ndd, settings, figpath)
return nothing
end
function _plot_pg_pf_diff!(
ax::PyObject, # axes to draw power grid onto
ndd::Dict{String,<:Any}, # NDD with (new) power flow
ref_ndd::Dict{String,<:Any}, # NDD with reference power flow
settings = Dict{String,Any}(), # plot settings
figpath = "" # where to save the figure
)
### Draw power grid graph
nx = pyimport("networkx")
G::PyObject = nx.Graph() # empty graph
### Plot buses into graph
G, bus_markers, bus_labels = _draw_buses!(G, ndd, settings)
### Plot branches into graph
G, br_markers, br_labels, br_cbar = _draw_br_pf_diff!(
G, ndd, ref_ndd, settings
)
### Check for a predefined area to show
if haskey(settings, "area")
area = settings["area"]
plt.xlim(area[1], area[2])
plt.ylim(area[3], area[4])
end
### Axes settings
ax.tick_params(
left = settings["draw_ticks"][1],
bottom = settings["draw_ticks"][2],
labelleft = settings["draw_ticks"][3],
labelbottom = settings["draw_ticks"][4]
)
plt.xlabel(settings["xlabel"])
plt.ylabel(settings["ylabel"], rotation=90)
### Draw legend, if wanted
if settings["draw_legend"] == true
all_markers = vcat(bus_markers, br_markers)
all_labels = vcat(bus_labels, br_labels)
plt.legend(all_markers, all_labels)
end
plt.savefig(figpath, bbox_inches="tight") # save figure
plt.close("all") # close figure
return ax, G
end
function _draw_br_pf_diff!(
G::PyObject, # power grid graph
ndd::Dict{String,<:Any}, # NDD with (new) power flow
ref_ndd::Dict{String,<:Any}, # NDD with reference power flow
settings::Dict{String,<:Any} # dictionary containing plot settings
)
pos = Dict(
b["index"] => (b["bus_lon"], b["bus_lat"])
for b in collect(values(ndd["bus"]))
) # geographic bus locations
branches = collect(values(ndd["branch"])) # branch dictionaries
### Get edges contained in the NDD and the loading difference
edges = Array{Tuple{Int64,Int64},1}() # array for edges
bl_diff = Array{Float64,1}() # array for branch load differences
for (i, br) in ndd["branch"]
if br["br_status"] == 1
push!(edges, (br["f_bus"], br["t_bus"]))
pf_type = settings["Branches"]["pf_type"]
push!(bl_diff, br[pf_type] - ref_ndd["branch"][i][pf_type])
end
end
### Draw edges and color them according to bl_diff
mcolors = pyimport("matplotlib.colors")
offset = mcolors.TwoSlopeNorm(
vcenter=0, vmin=minimum(bl_diff), vmax=maximum(bl_diff)
)
vmin, vmax = minimum(offset(bl_diff)), maximum(offset(bl_diff))
cmap = plt.get_cmap(settings["Branches"]["cmap"])
nx = pyimport("networkx")
drawnedges = nx.draw_networkx_edges(
G, pos,
width = settings["Branches"]["br_lw"],
edgelist = edges,
edge_color = offset(bl_diff),
edge_vmin = vmin,
edge_vmax = vmax,
edge_cmap = cmap
)
### Add colorbar
sm = plt.cm.ScalarMappable(cmap=cmap, offset)
cbar = plt.colorbar(sm)
cbar.ax.set_ylabel(
settings["Branches"]["cbar_label"], rotation=-90, va="bottom"
)
return G, [], [], cbar
end