Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ jobs:
# Since EnergyModelsGUI doesn't have binary dependencies,
# only test on a subset of possible platforms.
include:
- version: '1' # The latest point-release (Linux)
- version: '1.11' # The latest point-release (Linux)
os: ubuntu-latest
arch: x64
#- version: '1' # The latest point-release (Windows)
#- version: '1.11' # The latest point-release (Windows)
# os: windows-latest
# arch: x64
- version: 'lts' # lts
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/documentation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
- uses: actions/checkout@v2
- uses: julia-actions/setup-julia@latest
with:
version: '1'
version: '1.11'
- run: sudo apt-get update && sudo apt-get install -y xorg-dev mesa-utils xvfb libgl1 freeglut3-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev libxext-dev xsettingsd x11-xserver-utils
- name: Install dependencies
shell: julia --color=yes --project=docs/ {0}
Expand Down
14 changes: 14 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
# Release notes

## Version 0.5.17 (2025-11-09)

### Bugfix

* Fix bug that made nodes/areas disappear when plotting too many objects (max z_level is 10000).
* Fix square_intersection function.

### Enhancements

* Use `Float32` instead of `Number`/`Real`/`Float64` for coordinate related computations in topo (also `Point2f` instead of `Tuple` and `Vector`).
* Remove redundant `notify_component` function and `Observable`s (use the `@lift` macro instead).
* Improve performance of updates to `ax_info`.
* Add missing tests for show-function on the types `AbstractSystem` and `ProcInvData`, and improve code structure.

## Version 0.5.16 (2025-09-24)

### Enhancement
Expand Down
4 changes: 3 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "EnergyModelsGUI"
uuid = "737a7361-d3b7-40e9-b1ac-59bee4c5ea2d"
authors = ["Jon Vegard Venås <JonVegard.Venas@sintef.no>", "Magnus Askeland <Magnus.Askeland@sintef.no>", "Shweta Tiwari <Shweta.Tiwari@sintef.no>"]
version = "0.5.16"
version = "0.5.17"

[deps]
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
Expand All @@ -17,6 +17,7 @@ GeoJSON = "61d90e0f-e114-555e-ac52-39dfb47a3ef9"
GeoMakie = "db073c08-6b98-4ee5-b6a4-5efafb3259c6"
HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3"
ImageMagick = "6218d12a-5da1-5696-b52f-db25d2ecc6d1"
IntervalSets = "8197267c-284f-5f27-9208-e0e47529a953"
JuMP = "4076af6c-e467-56ae-b986-b466b2749572"
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
PrettyTables = "08abe8d2-0d0c-5749-adfa-8a2ac140af0d"
Expand Down Expand Up @@ -47,6 +48,7 @@ GeoJSON = "0.8"
GeoMakie = "=0.7.12"
HTTP = "1.10"
ImageMagick = "1.3"
IntervalSets = "<0.7.12"
JuMP = "1.22"
Pkg = "1.9"
PrettyTables = "2.3"
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ Visualization of the results after simulations will be added at a later stage.

The EnergyModelsGUI package has taken inspiration from the source code of [ModelingToolkitDesigner](https://github.com/bradcarman/ModelingToolkitDesigner.jl) as a starting point for development.

> [!WARNING]
> EnergyModelsGUI.jl currently does not support Julia verison 1.12 due to a breaking change in GLMakie. It is assumed that this issue will resolve soon in the future.

## Usage

If you already have constructed a `case` in EMX you can view this case with
Expand Down
7 changes: 3 additions & 4 deletions src/datastructures.jl
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,7 @@ energy system designs in Julia.
- **`components::Vector{EnergySystemDesign}`** is the components of the system, stored
as an array of EnergySystemDesign objects.
- **`connections::Vector{Connection}`** are the connections between system parts.
- **`xy::Observable{Tuple{Real,Real}}`** are the coordinates of the system, observed for
changes.
- **`xy::Observable{<:Point2f}`** are the coordinates of the system, observed for changes.
- **`icon::String`** is the optional (path to) icons associated with the system, stored as
a string.
- **`color::Observable{Symbol}`** is the color of the system, observed for changes and
Expand All @@ -138,7 +137,7 @@ mutable struct EnergySystemDesign <: AbstractGUIObj
id_to_icon_map::Dict
components::Vector{EnergySystemDesign}
connections::Vector
xy::Observable{Tuple{Real,Real}}
xy::Observable{<:Point2f}
icon::String
color::Observable{Symbol}
wall::Observable{Symbol}
Expand All @@ -152,7 +151,7 @@ function EnergySystemDesign(
id_to_icon_map::Dict,
components::Vector{EnergySystemDesign},
connections::Vector,
xy::Observable{Tuple{Real,Real}},
xy::Observable{<:Point2f},
icon::String,
color::Observable{Symbol},
wall::Observable{Symbol},
Expand Down
52 changes: 31 additions & 21 deletions src/setup_GUI.jl
Original file line number Diff line number Diff line change
Expand Up @@ -79,18 +79,18 @@ function GUI(
# Set variables
vars::Dict{Symbol,Any} = Dict(
:title => Observable("top_level"),
:Δh => 0.05, # Sidelength of main box
:Δh => Observable(0.05f0), # Sidelength of main box
:coarse_coast_lines => coarse_coast_lines,
:Δh_px => 50, # Pixel size of a box for nodes
:markersize => 15, # Marker size for arrows in connections
:boundary_add => 0.2, # Relative to the xlim/ylim-dimensions, expand the axis
:boundary_add => 0.2f0, # Relative to the xlim/ylim-dimensions, expand the axis
:line_sep_px => 2, # Separation (in px) between lines for connections
:connection_linewidth => 2, # line width of connection lines
:ax_aspect_ratio => 1.0, # Aspect ratio for the topology plotting area
:fontsize => fontsize, # General font size (in px)
:linewidth => 1.2, # Width of the line around boxes
:parent_scaling => 1.1, # Scale for enlargement of boxes around main boxes for nodes for parent systems
:icon_scale => 0.9, # scale icons w.r.t. the surrounding box in fraction of Δh
:icon_scale => 0.9f0, # scale icons w.r.t. the surrounding box in fraction of Δh
:two_way_sep_px => 10, # No pixels between set of lines for nodes having connections both ways
:selection_color => :green2, # Colors for box boundaries when selection objects
:investment_lineStyle => Linestyle([1.0, 1.5, 2.0, 2.5] .* 5), # linestyle for investment connections and box boundaries for nodes
Expand Down Expand Up @@ -134,16 +134,16 @@ function GUI(
vars[:hide_topo_ax_decorations] = hide_topo_ax_decorations
vars[:expand_all] = expand_all

vars[:xlimits] = Vector{Float64}([0.0, 1.0])
vars[:ylimits] = Vector{Float64}([0.0, 1.0])
vars[:xlimits] = Vector{Float32}([0.0f0, 1.0f0])
vars[:ylimits] = Vector{Float32}([0.0f0, 1.0f0])

vars[:topo_title_loc_x] = Observable(0.0)
vars[:topo_title_loc_y] = Observable(0.0)
vars[:topo_title_loc_x] = Observable(0.0f0)
vars[:topo_title_loc_y] = Observable(0.0f0)

# Create iterables for plotting objects in layers (z-direction) such that nodes are
# neatly placed on top of each other and lines are beneath nodes
vars[:z_translate_lines] = 1000
vars[:z_translate_components] = 5000
vars[:z_translate_lines] = 10.0f0
vars[:z_translate_components] = 50.0f0

vars[:selected_systems] = []

Expand All @@ -162,10 +162,12 @@ function GUI(
"\tholding x while scrolling over plots will zoom in/out in the x-direction.\n",
"\tholding y while scrolling over plots will zoom in/out in the y-direction.\n\n",
"Left-clicking a component will put information about this component here.\n\n",
"Clicking a plot below enables you to pin this plot (hitting the `pin\n\
current plot` button) for comparison with other plots.\n",
"Clicking a plot below enables you to pin this plot (hitting the `pin\n",
"current plot` button) for comparison with other plots.\n",
"Use the `Delete` button to unpin a selected plot.",
)
vars[:info_text] = Observable(vars[:default_text])
vars[:summary_text] = Observable("No model results")
vars[:dragging] = Ref(false)
vars[:ctrl_is_pressed] = Ref(false)

Expand Down Expand Up @@ -410,8 +412,8 @@ function create_makie_objects(vars::Dict, design::EnergySystemDesign)
# Add text at the top left of the axis domain (to print information of the selected/hovered node/connection)
text!(
ax_info,
vars[:default_text];
position = (0.01, 0.99),
vars[:info_text];
position = (0.01f0, 0.99f0),
align = (:left, :top),
fontsize = vars[:fontsize],
)
Expand All @@ -428,8 +430,8 @@ function create_makie_objects(vars::Dict, design::EnergySystemDesign)
# Add text at the top left of the axis domain (to print information of the selected/hovered node/connection)
text!(
ax_summary,
"No model results";
position = (0.01, 0.99),
vars[:summary_text];
position = (0.01f0, 0.99f0),
align = (:left, :top),
fontsize = vars[:fontsize],
)
Expand Down Expand Up @@ -467,7 +469,7 @@ function create_makie_objects(vars::Dict, design::EnergySystemDesign)
expand_all_toggle = Makie.Toggle(gridlayout_taskbar[1, 8]; active = vars[:expand_all])

# Add the following to add flexibility
Makie.Label(gridlayout_taskbar[1, 9], ""; tellwidth = false)
Makie.Label(gridlayout_taskbar[1, 9], " "; tellwidth = false)

# Add buttons related to the ax_results object (where the optimization results are plotted)
Makie.Label(
Expand Down Expand Up @@ -539,11 +541,14 @@ function create_makie_objects(vars::Dict, design::EnergySystemDesign)
justification = :right,
)
available_data_menu = Makie.Menu(
gridlayout_results_taskbar2[1, 2]; halign = :left, fontsize = vars[:fontsize],
gridlayout_results_taskbar2[1, 2];
options = zip(["no options"], [nothing]),
halign = :left,
fontsize = vars[:fontsize],
)

# Add the following to add flexibility
Makie.Label(gridlayout_results_taskbar3[1, 1], ""; tellwidth = false)
Makie.Label(gridlayout_results_taskbar3[1, 1], " "; tellwidth = false)

reset_view_results_button = Makie.Button(
gridlayout_results_taskbar3[1, 2]; label = "reset view",
Expand Down Expand Up @@ -626,7 +631,7 @@ function create_makie_objects(vars::Dict, design::EnergySystemDesign)

# Ensure that menus are on top
for menu ∈ values(menus)
translate!(menu.blockscene, 0, 0, vars[:z_translate_components] + 2000)
translate!(menu.blockscene, 0.0f0, 0.0f0, vars[:z_translate_components] + 2000.0f0)
end

# Collect all toggles into a dictionary
Expand All @@ -638,14 +643,19 @@ function create_makie_objects(vars::Dict, design::EnergySystemDesign)
)

# Update the title of the figure
vars[:topo_title_obj] = text!(
topo_title_obj = text!(
ax,
vars[:topo_title_loc_x],
vars[:topo_title_loc_y];
text = vars[:title],
fontsize = vars[:fontsize],
)
Makie.translate!(vars[:topo_title_obj], 0, 0, vars[:z_translate_components] + 999)
Makie.translate!(
topo_title_obj,
0.0f0,
0.0f0,
vars[:z_translate_components] + 999.0f0,
)

return fig, buttons, menus, toggles, axes, legends
end
23 changes: 11 additions & 12 deletions src/setup_topology.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ the function initializes the `EnergySystemDesign`.
- **`design_path::String=""`** is a file path or identifier related to the design.
- **`id_to_color_map::Dict`** is a dictionary of resources and their assigned colors.
- **`id_to_icon_map::Dict`** is a dictionary of nodes and their assigned icons.
- **`x::Real=0.0`** is the initial x-coordinate of the system.
- **`y::Real=0.0`** is the initial y-coordinate of the system.
- **`x::Float32=0.0f0`** is the initial x-coordinate of the system.
- **`y::Float32=0.0f0`** is the initial y-coordinate of the system.
- **`icon::String=""`** is the optional (path to) icons associated with the system, stored as
a string.
- **`parent::Union{Symbol, Nothing}=nothing`** is a parent reference or indicator.
Expand All @@ -27,8 +27,8 @@ function EnergySystemDesign(
design_path::String = "",
id_to_color_map::Dict = Dict(),
id_to_icon_map::Dict = Dict(),
x::Real = 0.0,
y::Real = 0.0,
x::Float32 = 0.0f0,
y::Float32 = 0.0f0,
icon::String = "",
)
# Create the path to the file where existing design is stored (if any)
Expand All @@ -53,7 +53,7 @@ function EnergySystemDesign(

# Create an observable for the coordinate xy that can be inherited as the coordinate
# parent_xy
xy::Observable{Tuple{Real,Real}} = Observable((x, y))
xy::Observable{Point2f} = Observable(Point2f(x, y))

# Create an iterator for the current system
elements = get_children(system)
Expand All @@ -73,23 +73,22 @@ function EnergySystemDesign(

# Extract x and y coordinates from file, or from structure or add defaults
if haskey(system_info, "x") && haskey(system_info, "y")
x = system_info["x"]
y = system_info["y"]
x = Float32(system_info["x"])
y = Float32(system_info["y"])
elseif isa(system, SystemGeo)
if hasproperty(element, :lon) && hasproperty(element, :lat)
# assigning longitude and latitude
x = element.lon
y = element.lat
x = Float32(element.lon)
y = Float32(element.lat)
else
@error "Missing lon and/or lat coordinates"
end
else
if element == get_ref_element(system)
x = parent_x
y = parent_y
x, y = parent_x, parent_y
else # place nodes in a circle around the parents availability node
x, y = place_nodes_in_circle(
nodes_count, current_node, 1, parent_x, parent_y,
nodes_count, current_node, 1.0f0, parent_x, parent_y,
)
current_node += 1
end
Expand Down
7 changes: 4 additions & 3 deletions src/utils_GUI/GUI_utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ function toggle_selection_color!(gui::GUI, selection::Connection, selected::Bool
plots = selection.plots
if selected
for plot ∈ plots
for plot_sub ∈ plot[]
for plot_sub ∈ plot
plot_sub.color = get_selection_color(gui)
end
end
else
colors::Vector{RGB} = selection.colors
no_colors::Int64 = length(colors)
for plot ∈ plots
for (i, plot_sub) ∈ enumerate(plot[])
for (i, plot_sub) ∈ enumerate(plot)
plot_sub.color = colors[((i-1)%no_colors)+1]
end
end
Expand Down Expand Up @@ -399,7 +399,8 @@ function initialize_available_data!(gui)
investment_overview *= "Investment overview (CAPEX):\n"
investment_overview *= inv_overview_components
end
get_ax(gui, :summary).scene.plots[1][1][] = investment_overview
summary_text = get_var(gui, :summary_text)
summary_text[] = investment_overview
else
if !isempty(model)
@warn "Total quantities were not computed as model does not contain a feasible solution"
Expand Down
Loading
Loading