#* Utility functions for various plotting functions #*------------------------------------------------------------------------------ #= Returns the minimal and maximal values of bus longitude and latitude coordinates contained a dictionary. An offset can be used to arbitrarily increase the area. =# function _get_pg_area(pos::Dict{Int64,Tuple{Float64,Float64}}, offset=0.) locs = collect(values(pos)) lon_min = minimum(p -> p[1], locs) - offset lon_max = maximum(p -> p[1], locs) + offset lat_min = minimum(p -> p[2], locs) - offset lat_max = maximum(p -> p[2], locs) + offset return lon_min, lon_max, lat_min, lat_max end function _get_pg_area(network_data::Dict{String,<:Any}, offset=0.) pos = Dict( b["index"] => (b["bus_lon"], b["bus_lat"]) for b in collect(values(network_data["bus"])) ) # geographic bus locations return _get_pg_area(pos, offset) end #*------------------------------------------------------------------------------ #= Returns isolated buses that are not connected to any active branch. =# function _get_isolated_buses(network_data::Dict{String,<:Any}) ### Find buses connected to active branches connected_buses = vcat( [br["f_bus"] for br in values(network_data["branch"]) if br["br_status"] == 1], [br["t_bus"] for br in values(network_data["branch"]) if br["br_status"] == 1] ) ### Find isolated buses isolated_buses = [ b["bus_i"] for b in values(network_data["bus"]) if b["bus_i"] ∉ connected_buses ] return unique(isolated_buses) end #*------------------------------------------------------------------------------ #= Function for recursively merging two dictionaries (used for updating the dictionary containing plot settings). =# _recursive_merge(x::AbstractDict,y::AbstractDict) = merge(_recursive_merge,x,y) _recursive_merge(x,y) = y #= Returns a dictionary of default plot settings for various plotting functions. =# function _default_settings(func::Symbol) if func == :plot_pg defaults = Dict( ### Settings for _draw_buses! "Buses" => Dict( "Generator" => Dict( "marker" => "s", "size" => 30, "color" => "darkorange", "alpha" => 1, "label" => "Generators", "show" => true ), "Load and generator" => Dict( "marker" => "s", "size" => 30, "color" => "darkorange", "alpha" => 1, "label" => "nolabel", "show" => true ), "Slack" => Dict( "marker" => "s", "size" => 70, "color" => "red", "alpha" => 0.6, "label" => "Slack", "show" => true ), "Load" => Dict( "marker" => "o", "size" => 15, "color" => "limegreen", "alpha" => 0.7, "label" => "Loads", "show" => true ), "Empty bus" => Dict( "marker" => "o", "size" => 2, "color" => "black", "alpha" => 0.3, "label" => "Empty buses", "show" => true, "show_isolated" => false ) ), ### Settings for _draw_branches! "Branches" => Dict( "br_status" => "active", # plot only "active", "inactive" or "all" branches "br_coloring" => "equal", # how to color branches (can be set to "equal", "voltage", "MW-loading", "Mvar-loading" or "MVA-loading") "br_color" => "k", # default color for "equal" coloring "br_lw" => 2, "br_alpha" => 1 ), "Wind" => Dict( "levels" => 200, "cmap" => "Purples", "alpha" => 1, "cbar_label" => L"\mathrm{wind\, speed\, in\,} m/s" ), "draw_ticks" => [true, true, true, true], # whether to show ticks "draw_legend" => true, # whether to draw a legend "xlabel" => L"Longitude in $°$", "ylabel" => L"Latitude in $°$" ) elseif func == :plot_pg_overhead_tl_segments defaults = Dict( ### Settings for _draw_buses! "Buses" => Dict( "Generator" => Dict( "marker" => "s", "size" => 30, "color" => "darkorange", "alpha" => 1, "label" => "Generators", "show" => true ), "Load and generator" => Dict( "marker" => "s", "size" => 30, "color" => "darkorange", "alpha" => 1, "label" => "nolabel", "show" => true ), "Slack" => Dict( "marker" => "s", "size" => 70, "color" => "red", "alpha" => 0.6, "label" => "Slack", "show" => true ), "Load" => Dict( "marker" => "o", "size" => 15, "color" => "limegreen", "alpha" => 0.7, "label" => "Loads", "show" => true ), "Empty bus" => Dict( "marker" => "o", "size" => 2, "color" => "black", "alpha" => 0.3, "label" => "Empty buses", "show" => true ) ), "d_twrs" => 161.0, "node_size" => .0005, "alpha" => 1, "draw_ticks" => [true, true, true, true], # whether to show ticks "draw_legend" => true, # whether to draw a legend "xlabel" => L"Longitude in $°$", "ylabel" => L"Latitude in $°$", ) elseif func == :scatter_branchloads defaults = Dict( "x_pf_type" => "MVA-loading", "y_pf_type" => "MVA-loading", "size" => 15, "cmap" => "seismic", # "coolwarm", # cividis_r "ec" => "k", "lw" => .1, "alpha" => 1., "xlabel" => "", "ylabel" => "" ) elseif func == :plot_pg_pf_diff defaults = Dict( "Branches" => Dict( "pf_type" => "MVA-loading", "cmap" => "coolwarm", "cbar_label" => L"Line loading difference $(F^{\mathrm{new}}_{ij}-F^{\mathrm{}}_{ij})/C_{ij}$" ) ) defaults = _recursive_merge(_default_settings(:plot_pg), defaults) else throw(ArgumentError("Unknown function $func.")) end return defaults end