Skip to content

Commit

Permalink
82 - arrows on powerflow plot (#101)
Browse files Browse the repository at this point in the history
  • Loading branch information
bryanluu authored Jul 9, 2022
1 parent 62c3038 commit 504d7cc
Show file tree
Hide file tree
Showing 9 changed files with 191 additions and 55 deletions.
3 changes: 3 additions & 0 deletions docs/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@ PowerPlots = "229d1e32-5c67-4c9a-a884-d6a3a7f23cfa"
Setfield = "efcf1570-3423-57d1-acb7-fd33fddbac46"
UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
VegaLite = "112f6efa-9a02-5b7d-90c0-432ed331239a"

[compat]
PowerModels = "^0.19.2"
28 changes: 15 additions & 13 deletions docs/src/examples/advanced examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ using ColorSchemes
using Setfield
using JuMP, Ipopt
case = parse_file("case14.m")
sol = run_ac_opf(case, optimizer_with_attributes(Ipopt.Optimizer, "print_level"=>0))
update_data!(case,sol["solution"])
result = solve_ac_opf(case, optimizer_with_attributes(Ipopt.Optimizer, "print_level"=>0))
update_data!(case,result["solution"])
plot1 = powerplot(case,
# bus_data=:vm,
Expand All @@ -21,18 +21,18 @@ plot1 = powerplot(case,
gen_data_type=:quantitative,
branch_data=:pt,
branch_data_type=:quantitative,
branch_color=["black","black","red"],
gen_color=["black","black","red"]
branch_color=["DimGray","red"],
gen_color=["DimGray","red"]
)
plot1.layer[1]["transform"] = Dict{String, Any}[
Dict("calculate"=>"abs(datum.pt)/datum.rate_a*100", "as"=>"branch_Percent_Loading"),
Dict("calculate"=>"abs(datum.pt)", "as"=>"BranchPower")
]
plot1.layer[1]["encoding"]["color"]["field"]="branch_Percent_Loading"
plot1.layer[1]["encoding"]["color"]["title"]="Branch Utilization %"
plot1.layer[1]["encoding"]["color"]["scale"]["domain"]=[0,100]
plot1.layer[1]["encoding"]["size"]=Dict("field"=>"BranchPower", "title"=>"Branch BaseMW", "type"=>"quantitative", "scale"=>Dict("range"=>[3,10]))
plot1.layer[1]["layer"][1]["encoding"]["color"]["field"]="branch_Percent_Loading"
plot1.layer[1]["layer"][1]["encoding"]["color"]["title"]="Branch Utilization %"
plot1.layer[1]["layer"][1]["encoding"]["color"]["scale"]["domain"]=[0,100]
#plot1.layer[1]["layer"][1]["encoding"]["size"]=Dict("field"=>"BranchPower", "title"=>"Branch BaseMW", "type"=>"quantitative", "scale"=>Dict("range"=>[3,10]))
plot1.layer[4]["transform"] = Dict{String, Any}[
Expand All @@ -44,7 +44,7 @@ plot1.layer[4]["encoding"]["color"]["scale"]["domain"]=[0,100]
plot1.layer[4]["encoding"]["color"]["title"]="Gen Utilization %"
plot1.layer[4]["encoding"]["size"]=Dict("field"=>"GenPower", "title"=>"Gen BaseMW", "type"=>"quantitative", "scale"=>Dict("range"=>[300,1000]))
plot1.layer[1]["encoding"]["color"]["legend"]=Dict("orient"=>"bottom-right", "offset"=>-30)
plot1.layer[1]["layer"][1]["encoding"]["color"]["legend"]=Dict("orient"=>"bottom-right", "offset"=>-30)
plot1.layer[4]["encoding"]["color"]["legend"]=Dict("orient"=>"bottom-right")
@set! plot1.resolve.scale.size=:independent
Expand Down Expand Up @@ -87,12 +87,14 @@ end
color_range = colorscheme2array(ColorSchemes.colorschemes[:tableau_10])
color_range = [color_range[i] for i in[1,2,4,3]]
plot1 = powerplot(case; bus_data=:block, gen_data=:block, branch_data=:block, node_color=color_range, branch_color=color_range)
plot1 = powerplot(case; bus_data=:block, gen_data=:block, branch_data=:block, node_color=color_range, branch_color=color_range, show_flow=false)
@set! plot1.resolve.scale.color=:shared # share color scale for all components
for l in plot1.layer #set all layer titles to "Load Blocks"
l["encoding"]["color"]["title"]="Load Blocks"
end
plot1.layer[1]["layer"][1]["encoding"]["color"]["title"]="Load Blocks"
plot1.layer[2]["encoding"]["color"]["title"]="Load Blocks"
plot1.layer[3]["encoding"]["color"]["title"]="Load Blocks"
plot1.layer[4]["encoding"]["color"]["title"]="Load Blocks"
plot1
```
Expand Down
43 changes: 29 additions & 14 deletions docs/src/examples/basic examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ Aliases to overide all node and edge sizes.
powerplot(data, node_size=1000, edge_size=10, width=300, height=300)
```

## Visualizing System Data
# Visualizing System Data
Component data values from the PowerModels dictionary can be plotted by specfying the dictionary key. The key can be either a string or a symbol. The data type can be `:ordinal`, `:nominal`, or `:quantitative`.

```@example power_data
Expand All @@ -59,7 +59,7 @@ p = powerplot(data, bus_data="bus_type",
)
```

### Color Ranges
## Color Ranges
Color ranges are automatically interpolated from a range that is provided. If only a single color is given, the component will not change color based on the data.

```@example power_data
Expand All @@ -71,7 +71,7 @@ p = powerplot(data,
)
```

### Color Schemes
## Color Schemes
Color schemes from the package `ColorSchemes.jl` can also be used to specify a color range.

```@example power_data
Expand All @@ -83,20 +83,23 @@ powerplot(data;
width=300, height=300
)
```
## Distribution Grids
Open a three-phase distribution system case using [PowerModelsDistribution.jl](https://github.com/lanl-ansi/PowerModelsDistribution.jl) and run the command `powerplot` on the data.

```
using PowerModelsDistribution
using PowerPlots
eng = PowerModelsDistribution.parse_file("$(joinpath(dirname(pathof(PowerModelsDistribution)), ".."))/test/data/opendss/case3_unbalanced.dss")
math = transform_data_model(eng)
powerplot(math)
# example works, but fails to run in documentation
# Power Flow
If the variables `pf` (power from) and `pt` (power to) exist in the data, power flow directions can be visualized using the `show_flow` boolean toggle (true by default).

```@example
# Solve AC power flow and add values to data dictionary
using Ipopt, PowerModels, PowerPlots
data = parse_file("$(joinpath(dirname(pathof(PowerModels)), ".."))/test/data/matpower/case5.m")
result = solve_ac_opf(data, Ipopt.Optimizer)
update_data!(data, result["solution"])
p = powerplot(data, show_flow=true)
```

## Multinetworks
# Multinetworks
`powerplot` detects if a network is a multinetwork and will create a slider to select which network to view.

```@example power_data
data_mn = PowerModels.replicate(data, 5)
Expand All @@ -108,4 +111,16 @@ for (nwid,nw) in data_mn["nw"]
end
powerplot(data_mn, branch_data=:value, branch_data_type=:quantitative)
```
```

# Distribution Grids
Open a three-phase distribution system case using [PowerModelsDistribution.jl](https://github.com/lanl-ansi/PowerModelsDistribution.jl) and run the command `powerplot` on the data.

```
using PowerModelsDistribution
using PowerPlots
eng = PowerModelsDistribution.parse_file("$(joinpath(dirname(pathof(PowerModelsDistribution)), ".."))/test/data/opendss/case3_unbalanced.dss")
math = transform_data_model(eng)
powerplot(math)
# example works, but fails to run in documentation
```
13 changes: 11 additions & 2 deletions docs/src/parameters.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,21 @@ These paramters modify the entire plot.

## Component Parameters
These parameters modify a specific component.
### Toggles
There are several component 'toggle' parameters that control whether certain display properties of components are on or off. These accept boolean values.

| Keyword | Description | Default |
| ------- | ----------- | ------- |
| `show_flow` | whether flow arrows are displayed | `true` |
| `show_flow_legend` | whether the legend for the flow arrows is shown | `false` |

### Color
The color arguments can accept several inputs. A single color can be specified using a color name as a symbol or a string. [CSS color](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value) names are supported. In addition, hex color values in a string are supported.

```julia
powerplot(case; branch_color=:yellow)
powerplot(case; branch_color="yellow")
powerplot(case; branch_color="#FFA71A)
powerplot(case; branch_color="#FFA71A")
```

A color range can be created by using several colors in an array. The range is used when component data is specified.
Expand All @@ -47,6 +55,7 @@ powerplot(case; branch_color=colorscheme2array(ColorSchemes.colorschemes[:tablea
| `bus_color` | set the color of a bus | `["#31A354", "#57B46F", "#7CC68A", "#A1D8A5", "#C7E9C0"]` |
| `node_color` | set the color of all buses and generators | N/A |
| `edge_color` | set the color of all branches, DC lines, and connectors | N/A|
| `flow_color` | set the color of flow arrows | `:black`


### Size
Expand Down Expand Up @@ -93,4 +102,4 @@ powerplot(case; gen_data=:index, gen_data_type=:nominal) # the index is a discre
| `dcline_data_type` | set the data type of a DC line | `:nominal` |
| `connector_data_type` | set the data type of a connector | `:nominal` |
| `gen_data_type` | set the data type of a generator | `:nominal` |
| `bus_data_type` | set the data type of a bus | `:nominal` |
| `bus_data_type` | set the data type of a bus | `:nominal` |
8 changes: 8 additions & 0 deletions src/core/attribute_validation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,14 @@ function _validate_plot_attributes!(plot_attributes::Dict{Symbol, Any})
Memento.warn(_LOGGER, "Value for $(repr(attr)) should be given as a String or Symbol")
end
end

# validate boolean attributes
for attr in _boolean_attributes
value = plot_attributes[attr]
if !(typeof(value) <: Bool)
Memento.warn(_LOGGER, "Value for $(repr(attr)) should be given as a Bool")
end
end
end


Expand Down
15 changes: 13 additions & 2 deletions src/core/options.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ default_plot_attributes = Dict{Symbol, Any}(
:connector_color => [:gray],
:dcline_color => color_schemes[:purples],
:storage_color => color_schemes[:oranges],
:flow_color => :black,
:gen_size => 5e2,
:bus_size => 5e2,
:branch_size => 5,
Expand All @@ -36,6 +37,8 @@ default_plot_attributes = Dict{Symbol, Any}(
:branch_data_type => "nominal",
:dcline_data_type => "nominal",
:storage_data_type => "nominal",
:show_flow => true,
:show_flow_legend => false,
:parallel_edge_offset => 0.05,
);

Expand All @@ -61,6 +64,9 @@ const attribute_aliases = Dict(
:branch_size => [:branchsize, :line_size, :edge_size],
:dcline_size => [:dclinesize, :line_size, :edge_size],
:connector_size => [:connectorsize, :edge_size],
:flow_color => [:flowcolor, :arrow_color, :arrowcolor],
:show_flow => [:flow, :showflow, :arrows, :show_arrows, :showarrows, :flows, :show_flows, :showflows],
:show_flow_legend => [:flowlegend, :flow_legend, :arrowlegend, :arrow_legend, :show_arrow_legend],
)

const _color_attributes = [ # color (String or Symbol) type parameters
Expand All @@ -69,7 +75,8 @@ const _color_attributes = [ # color (String or Symbol) type parameters
:branch_color,
:connector_color,
:storage_color,
:dcline_color
:dcline_color,
:flow_color
]
const _numeric_attributes = [ # numeric parameters
:gen_size,
Expand All @@ -93,4 +100,8 @@ const _label_attributes = [ # label (String or Symbol) type parameters
:branch_data_type,
:dcline_data_type,
:storage_data_type
]
]
const _boolean_attributes = [ # boolean type parameters
:show_flow,
:show_flow_legend,
]
29 changes: 28 additions & 1 deletion src/layouts/common.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

# re-export NetworkLayout algorithms
function Shell(; Ptype=Float64, nlist=Vector{Int}[], kwargs...)
NetworkLayout.Shell(; Ptype=Ptype, nlist=nlist)
Expand Down Expand Up @@ -77,6 +76,7 @@ function layout_network(case::Dict{String,<:Any};
end

apply_node_positions!(data,positions, PMG)
extract_layout_extent!(data, positions)

return data
end
Expand Down Expand Up @@ -116,3 +116,30 @@ function apply_node_positions!(data,positions, PMG)

return data
end

"Extract layout coordinate extent for scaling purposes"
function extract_layout_extent!(data::Dict{String,<:Any}, positions)
# find the extremes
min_x = min_y = Inf
max_x = max_y = -Inf
for pos in positions
x, y = pos
min_x, min_y = min(min_x, x), min(min_y, y)
max_x, max_y = max(max_x, x), max(max_y, y)
end

width, height = (max_x - min_x), (max_y - min_y)
padding = min(50, 0.2 * (width + height) / 2) # set padding to be minimum of 50 px or 20% the average of the width and height

# add to data
data["layout_extent"] = Dict{String, Any}()
data["layout_extent"]["min_x"] = min_x
data["layout_extent"]["min_y"] = min_y
data["layout_extent"]["max_x"] = max_x
data["layout_extent"]["max_y"] = max_y
data["layout_extent"]["width"] = width
data["layout_extent"]["height"] = height
data["layout_extent"]["padding"] = padding

return data
end
Loading

0 comments on commit 504d7cc

Please sign in to comment.