Skip to content

Commit

Permalink
Migrate files from TulipaEnergyModel.jl (#2)
Browse files Browse the repository at this point in the history
* Add functions and tests

* Add missing files

* Clean project.toml, add prefix to functions

* Fix prefix and update list of dependencies

* Update data to fix tests

* Change dir to pkg dir

* Fix deprecated Pkg.dir function

* Disable nightly in testing workflow

* Fix lint

* Add documentation

* Add missing doc

* Remove redundant Pkg
  • Loading branch information
gnawin authored Feb 16, 2024
1 parent c9386b8 commit 00be448
Show file tree
Hide file tree
Showing 12 changed files with 277 additions and 21 deletions.
28 changes: 14 additions & 14 deletions .github/workflows/Test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,27 +34,27 @@ jobs:
version:
- "1.6"
- "1"
- "nightly"
# - "nightly"
os:
- ubuntu-latest
- macOS-latest
#- windows-latest
arch:
- x64
allow_failure: [false]
include:
- version: "nightly"
os: ubuntu-latest
arch: x64
allow_failure: true
- version: "nightly"
os: macOS-latest
arch: x64
allow_failure: true
#- version: "nightly"
# os: windows-latest
# arch: x64
# allow_failure: true
# include:
# - version: "nightly"
# os: ubuntu-latest
# arch: x64
# allow_failure: true
# - version: "nightly"
# os: macOS-latest
# arch: x64
# allow_failure: true
#- version: "nightly"
# os: windows-latest
# arch: x64
# allow_failure: true
steps:
- uses: actions/checkout@v3
- uses: julia-actions/setup-julia@v1
Expand Down
9 changes: 9 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,14 @@ uuid = "b0e16111-6728-43b3-a540-753ecafcbb71"
authors = ["TNO <[email protected]> and contributors"]
version = "0.1.0"

[deps]
CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0"
Colors = "5ae59095-9a9b-59fe-a467-6f913c188581"
GraphMakie = "1ecd5474-83a3-4783-bb4f-06765db800d2"
Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6"
MetaGraphsNext = "fa8bd995-216d-47f1-8a91-f3b68fbeb377"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
TulipaEnergyModel = "5d7bd171-d18e-45a5-9111-f1f11ac5d04d"

[compat]
julia = "1.6"
5 changes: 1 addition & 4 deletions docs/Project.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
# Don't forget to run
#
# pkg> dev ..
#
[deps]
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
TulipaEnergyModel = "5d7bd171-d18e-45a5-9111-f1f11ac5d04d"
TulipaPlots = "b0e16111-6728-43b3-a540-753ecafcbb71"

[compat]
Expand Down
1 change: 1 addition & 0 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ makedocs(;
),
pages = [
"Home" => "index.md",
"Example" => "example.md",
"Contributing" => "contributing.md",
"Dev setup" => "developer.md",
"Reference" => "reference.md",
Expand Down
19 changes: 19 additions & 0 deletions docs/src/developer.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,22 @@ If this is the first time you work with this repository, follow the instructions
```

- Then you can open a pull request and work with the reviewer to address any issues.

## Build and see the documentation locally

To build and see the documentation locally, first, navigate to the `docs` folder in your file explorer and open a terminal. Then, run `julia --project` (remember that `julia` must be part of your environment variables to call it from the command line). With the `julia` open, enter the `pkg` mode by pressing `]`. Check that the environment name is `docs`. The first time here, you have to run:

```julia-pkg
pkg> dev ..
pkg> update
```

Then, to build the documentation, run

```julia
julia> include("make.jl")
```

If you intend to rerun the build step, ensure you have the package `Revise` installed in your global environment, and run `using Revise` before including `make.jl`. Alternatively, close `julia` and reopen it.

After building, the documentation will be available in the folder `docs/build/`. Open the `index.html` file on the browser to see it.
35 changes: 35 additions & 0 deletions docs/src/example.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Example

TulipaPlots.jl has three functions for plotting: a time-series flows, a visualisation of the graph (with asset and flow capacities), and a bar graph of the initial and invested asset capacities. We show an example for plotting using the solution from the Norse case in TulipaEnergyModel.jl.

First obtain the solution:

```@example solution
using TulipaEnergyModel
using TulipaPlots
using Pkg # hide
dir = joinpath(dirname(pathof(TulipaEnergyModel)), "..", "test/inputs/Norse") # hide
# input_dir should be the path to Norse
energy_problem = run_scenario(dir)
```

Plot a single flow for a single representative period:

```@example solution
TulipaPlots.plot_single_flow(energy_problem, "Asgard_Solar", "Asgard_E_demand", 1)
```

Plot the graph, with asset and flow capacities:

```@example solution
TulipaPlots.plot_graph(energy_problem)
```

Graph the final capacities of assets:

```@example solution
TulipaPlots.plot_assets_capacity(energy_problem)
```

If you would like more custom plots, explore the code of [plot](https://github.com/TulipaEnergy/TulipaPlots.jl/blob/main/src/TulipaPlots.jl) for ideas.
7 changes: 7 additions & 0 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,10 @@ CurrentModule = TulipaPlots
# TulipaPlots

Documentation for [TulipaPlots](https://github.com/TulipaEnergy/TulipaPlots.jl).

This package contains plotting functions for TulipaEnergyModel.jl.

## Contents

```@contents
```
13 changes: 12 additions & 1 deletion src/TulipaPlots.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
module TulipaPlots

# Write your package code here.
# Packages

## Graphs
using Graphs, MetaGraphsNext

## Optimization
using TulipaEnergyModel

## Plots
using Plots, Colors, GraphMakie, GraphMakie.NetworkLayout, CairoMakie

include("plot.jl")

end
163 changes: 163 additions & 0 deletions src/plot.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
export plot_single_flow, plot_graph, plot_assets_capacity

"""
plot_single_flow(graph, asset_from, asset_to, rp)
plot_single_flow(energy_problem, asset_from, asset_to, rp)
Plot a single flow over a single representative period, given a graph or energy problem,
the "from" (exporting) asset, the "to" (importing) asset, and the representative period.
"""
function plot_single_flow(graph::MetaGraph, asset_from::String, asset_to::String, rp::Int64)
rp_partition = graph[asset_from, asset_to].partitions[rp]
time_dimension = 1:length(rp_partition)
flow_value = [graph[asset_from, asset_to].flow[(rp, B)] for B in rp_partition]

#TODO Rework using CairoMakie instead of Plots
Plots.plot(
time_dimension,
flow_value;
title = string("Flow from ", asset_from, " to ", asset_to, " for RP", rp),
titlefontsize = 10,
legend = false,
)
end

function plot_single_flow(
energy_problem::EnergyProblem,
asset_from::String,
asset_to::String,
rp::Int64,
)
plot_single_flow(energy_problem.graph, asset_from, asset_to, rp)
end

"""
plot_graph(graph)
plot_graph(energy_problem)
Given a graph or energy problem, plot the graph with the "final" (initial + investment) flow capacities,
represented by the thickness of the graph edges, as well as displayed values.
"""
function plot_graph(graph::MetaGraph)
# Choose colors
nodelabelcolor = RGB(0.345, 0.164, 0.376)
transportflowcolor = RGB(1, 0.647, 0)
assetflowcolor = RGB(0.988, 0.525, 0.110)
nodecolor = RGBA(0.345, 0.164, 0.376, 0.5)

node_labels = labels(graph) |> collect

# Create a temporary graph that has arrows both directions for transport
temp_graph = DiGraph(nv(graph))
for e in edges(graph)
add_edge!(temp_graph, e.src, e.dst)
if graph[node_labels[e.src], node_labels[e.dst]].is_transport
add_edge!(temp_graph, e.dst, e.src)
end
end

# Calculate node size based on initial and investment capacity
node_size = []
node_names = []
for a in node_labels
node_total_capacity =
graph[a].initial_capacity + graph[a].investable * graph[a].investment * graph[a].capacity
push!(node_names, "$a \n $(node_total_capacity)") # "Node Name, Capacity: ##"
push!(node_size, node_total_capacity)
end
node_size = node_size * 98 / maximum(node_size) .+ 5

# Calculate edge width (and set color) depending on type and (if transport) capacity
edge_colors = []
edge_width = []
edge_labels = []
for e in edges(temp_graph)
from = node_labels[e.src]
to = node_labels[e.dst]
edge_data = has_edge(graph, e.src, e.dst) ? graph[from, to] : graph[to, from]

if edge_data.is_transport
# Compare temp_graph to graph to determine export vs. import edges
total_trans_cap =
(
if has_edge(graph, e.src, e.dst)
edge_data.initial_export_capacity
else
edge_data.initial_import_capacity
end
) + edge_data.investable * edge_data.investment * edge_data.capacity
push!(edge_labels, string(total_trans_cap))
push!(edge_width, total_trans_cap)
push!(edge_colors, transportflowcolor)
else
push!(edge_labels, "")
push!(edge_width, 0)
push!(edge_colors, assetflowcolor)
end
end
edge_width = edge_width * 0.9 / (maximum(edge_width) == 0 ? 1 : maximum(edge_width)) .+ 0.1 # Normalize edge_width with minimum of 0.1 (just visible)

#TODO Show initial vs investment somehow (couldn't get node stroke to work)
f, ax, p = graphplot(
temp_graph;
node_size = node_size,
node_strokewidth = 0,
node_color = nodecolor,
ilabels = node_names,
ilabels_color = nodelabelcolor,
ilabels_fontsize = 10.0,
edge_width = edge_width * 10,
arrow_size = (edge_width .+ 2) * 10,
edge_color = edge_colors,
elabels = edge_labels,
elabels_fontsize = 10.0,
elabels_color = edge_colors,
)

#TODO Make these axis adjustments a calculation (so labels aren't cut off)
CairoMakie.xlims!(ax, -5.5, 5.5)
CairoMakie.ylims!(ax, -5, 6)
hidedecorations!(ax)
hidespines!(ax)

return f
end

function plot_graph(energy_problem::EnergyProblem)
plot_graph(energy_problem.graph)
end

"""
plot_assets_capacity(graph)
plot_assets_capacity(energy_problem)
Given a graph or energy problem, display a stacked bar graph of
the initial and invested capacity of each asset (initial + invested = total).
"""
function plot_assets_capacity(graph::MetaGraph)
asset_labels = labels(graph) |> collect

total_asset_cap = [
graph[a].initial_capacity + graph[a].investable * graph[a].investment * graph[a].capacity for
a in asset_labels
]
initial_cap = [graph[a].initial_capacity for a in asset_labels]
investment_cap =
[graph[a].investable * graph[a].investment * graph[a].capacity for a in asset_labels]

#TODO Rework using CairoMakie instead of Plots
Plots.plot(
[initial_cap, investment_cap];
seriestype = :bar,
xticks = (1:length(total_asset_cap), asset_labels),
xrotation = 90,
title = string("Total Capacity of Assets after Investment"),
titlefontsize = 10,
label = ["Initial Capacity" "Invested Capacity"],
)
end

function plot_assets_capacity(energy_problem::EnergyProblem)
plot_assets_capacity(energy_problem.graph)
end
1 change: 1 addition & 0 deletions test/Project.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
[deps]
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
TulipaEnergyModel = "5d7bd171-d18e-45a5-9111-f1f11ac5d04d"
7 changes: 5 additions & 2 deletions test/runtests.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
using TulipaEnergyModel
using TulipaPlots
using Test

@testset "TulipaPlots.jl" begin
# Write your tests here.
# Run all files in test folder starting with `test-` and ending with `.jl`
test_files = filter(file -> startswith("test-")(file) && endswith(".jl")(file), readdir(@__DIR__))
for file in test_files
include(file)
end
10 changes: 10 additions & 0 deletions test/test-plotting.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
@testset "Plotting" begin
dir = joinpath(dirname(pathof(TulipaEnergyModel)), "..", "test/inputs/Norse")
energy_problem = run_scenario(dir)
@testset "Codecov Demands Graphs" begin
# Prefix is used because TulipaEnergyModel also exports these functions
TulipaPlots.plot_single_flow(energy_problem, "Asgard_Solar", "Asgard_Battery", 1)
TulipaPlots.plot_graph(energy_problem)
TulipaPlots.plot_assets_capacity(energy_problem)
end
end

0 comments on commit 00be448

Please sign in to comment.