Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Visualize combined actions by dashed lines #28

Merged
merged 2 commits into from
Apr 14, 2024
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
5 changes: 5 additions & 0 deletions documentation/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ Description of of all notable changes made per version.
- Support writing and reading information about pathways to a binary file.
- Support import / export between text and binary dataset formats. See ``ap_import`` and
``ap_export`` commands.
- Visualize combinations of actions by dashed lines
- Added documentations (manuals and API)
- Moved repository to new location: https://github.com/Deltares-research/PathwaysGenerator
- Configured continuous integration. Every time we make changes, the source code is checked
(style and functionality). https://github.com/Deltares-research/PathwaysGenerator/actions


0.0.8
Expand Down
15 changes: 13 additions & 2 deletions source/package/adaptation_pathways/desktop/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,22 @@
from ..plot import (
pathway_graph_node_colours,
pathway_map_edge_colours,
pathway_map_edge_styles,
pathway_map_node_colours,
pathway_map_node_styles,
plot_classic_pathway_map,
plot_default_pathway_graph,
plot_default_pathway_map,
plot_default_sequence_graph,
sequence_graph_node_colours,
)
from ..plot.colour import (
Colour,
PlotColours,
default_edge_colours,
default_edge_style,
default_label_colour,
default_node_edge_colours,
default_node_style,
default_nominal_palette,
)
from ..plot.util import action_level_by_first_occurrence
Expand Down Expand Up @@ -126,7 +129,7 @@ def __init__(self, basename_pathname: str = ""):
self.actions: list[list] = [] # type: ignore
self.sequences: list[list[Action]] = [] # type: ignore
self.tipping_point_by_action: alias.TippingPointByAction = {} # type: ignore
self.colour_by_action_name: dict[str, Colour] = {} # type: ignore
self.colour_by_action_name: dict[str, alias.Colour] = {} # type: ignore

self.ui.action_open.setIcon(QtGui.QIcon(Path.icon("folder-open-table.png")))
self.ui.action_save.setIcon(QtGui.QIcon(Path.icon("disk.png")))
Expand Down Expand Up @@ -239,7 +242,9 @@ def eventFilter(self, object_, event):
def _plot_sequence_graph(self, sequence_graph: SequenceGraph) -> None:
plot_colours = PlotColours(
sequence_graph_node_colours(sequence_graph, self.colour_by_action_name),
default_node_style(),
default_edge_colours(sequence_graph),
default_edge_style(),
default_node_edge_colours(sequence_graph),
default_label_colour(),
)
Expand All @@ -253,7 +258,9 @@ def _plot_sequence_graph(self, sequence_graph: SequenceGraph) -> None:
def _plot_pathway_graph(self, pathway_graph: PathwayGraph) -> None:
plot_colours = PlotColours(
pathway_graph_node_colours(pathway_graph, self.colour_by_action_name),
default_node_style(),
default_edge_colours(pathway_graph),
default_edge_style(),
default_node_edge_colours(pathway_graph),
default_label_colour(),
)
Expand All @@ -267,7 +274,9 @@ def _plot_pathway_graph(self, pathway_graph: PathwayGraph) -> None:
def _plot_pathway_map(self, pathway_map: PathwayMap) -> None:
plot_colours = PlotColours(
pathway_map_node_colours(pathway_map, self.colour_by_action_name),
default_node_style(),
pathway_map_edge_colours(pathway_map, self.colour_by_action_name),
default_edge_style(),
default_node_edge_colours(pathway_map),
default_label_colour(),
)
Expand All @@ -281,7 +290,9 @@ def _plot_pathway_map(self, pathway_map: PathwayMap) -> None:
def _plot_pathway_classic_map(self, pathway_map: PathwayMap) -> None:
plot_colours = PlotColours(
pathway_map_node_colours(pathway_map, self.colour_by_action_name),
pathway_map_node_styles(pathway_map),
pathway_map_edge_colours(pathway_map, self.colour_by_action_name),
pathway_map_edge_styles(pathway_map),
default_node_edge_colours(pathway_map),
default_label_colour(),
)
Expand Down
8 changes: 5 additions & 3 deletions source/package/adaptation_pathways/desktop/model/action.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
from PySide6 import QtCore, QtGui
from PySide6.QtCore import Qt

from ...plot.colour import Colour
from ... import alias


class ActionModel(QtCore.QAbstractTableModel):

_actions: list[list]
_headers: tuple[str]
_colour_by_action_name: dict[str, Colour]
_colour_by_action_name: dict[str, alias.Colour]

def __init__(self, actions: list[list], colour_by_action_name: dict[str, Colour]):
def __init__(
self, actions: list[list], colour_by_action_name: dict[str, alias.Colour]
):

super().__init__()
self._actions = actions
Expand Down
5 changes: 2 additions & 3 deletions source/package/adaptation_pathways/desktop/model/sequence.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,19 @@

from ... import alias
from ...action import Action
from ...plot.colour import Colour


class SequenceModel(QtCore.QAbstractTableModel):
_sequences: list[list[Action]]
_tipping_point_by_action: alias.TippingPointByAction
_horizonal_headers: tuple[str, str, str]
_colour_by_action_name: dict[str, Colour]
_colour_by_action_name: dict[str, alias.Colour]

def __init__(
self,
sequences: list[list[Action]],
tipping_point_by_action: alias.TippingPointByAction,
colour_by_action_name: dict[str, Colour],
colour_by_action_name: dict[str, alias.Colour],
):
super().__init__()
self._sequences = sequences
Expand Down
4 changes: 2 additions & 2 deletions source/package/adaptation_pathways/io/dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ def read_dataset(
else:
message = (
f"Error while reading text dataset {basename_pathname}. "
"First tried reading a binary dataset with that name "
"but it does not exist."
"(First tried reading a binary dataset with that name "
"but it does not exist.)"
)
raise RuntimeError(message) from exception

Expand Down
4 changes: 3 additions & 1 deletion source/package/adaptation_pathways/io/text.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,9 @@ def read_sequences(
f"Found tipping point {tipping_point} "
f"for action {sequence[1]}, which already has "
f"tipping point {tipping_point_by_action[sequence[1]]}. "
"Actions must be associated with exactly one tipping point."
"Actions must be associated with exactly one tipping point. "
f"Action editions ({sequence[1]}[1], {sequence[1]}[2]) can be used for "
"multiple occurrences of the same action."
)

tipping_point_by_action[sequence[1]] = tipping_point
Expand Down
14 changes: 13 additions & 1 deletion source/package/adaptation_pathways/plot/alias.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,20 @@
"""

from ..action import Action
from .colour import Colour, Colours # pylint: disable=unused-import


# from .colour import Colour, Colours # pylint: disable=unused-import

Colour = tuple[float, float, float, float]
"""
A colour is represented by four floating point values [0, 1], representing RGBA values respectively
"""

Colours = list[Colour]
Style = str | tuple[int, tuple[int, int]]
Styles = list[Style]
FillStyle = str
FillStyles = list[Style]

ColourByAction = dict[Action, Colour]
ColourByActionName = dict[str, Colour]
57 changes: 35 additions & 22 deletions source/package/adaptation_pathways/plot/colour.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,7 @@
from dataclasses import dataclass

from ..graph import PathwayGraph, PathwayMap, SequenceGraph


Colour = tuple[float, float, float, float]
"""
A colour is represented by four floating point values [0, 1], representing RGBA values respectively
"""

Colours = list[Colour]
from . import alias


@dataclass
Expand All @@ -23,15 +16,19 @@ class PlotColours:
This class aggregates colours used when plotting graphs

:param node_colours: Fill colours for nodes
:param node_style: Fill style for nodes
:param edge_colours: Line colours for edges
:param edge_style: Line style for edges
:param node_edge_colours: Line colours for node outline
:param label_colour: Label colour for labels
"""

node_colours: Colours | None = None
edge_colours: Colours | None = None
node_edge_colours: Colours | None = None
label_colour: Colour | None = None
node_colours: list[alias.Colour | alias.Colours] | None = None
node_style: alias.FillStyle | list[alias.FillStyle | alias.FillStyles] | None = None
edge_colours: list[alias.Colour | alias.Colours] | None = None
edge_style: alias.Style | list[alias.Style | alias.Styles] | None = None
node_edge_colours: alias.Colours | None = None
label_colour: alias.Colour | None = None


nord_palette_nominal = [
Expand Down Expand Up @@ -79,7 +76,7 @@ class PlotColours:
"""


def default_nominal_palette() -> Colours:
def default_nominal_palette() -> alias.Colours:
"""
Return the default palette with nominal colours
"""
Expand All @@ -88,19 +85,28 @@ def default_nominal_palette() -> Colours:

def default_edge_colours(
graph: SequenceGraph | PathwayGraph,
) -> Colours:
) -> list[alias.Colour | alias.Colours]:
"""
For each edge in the graph, return a colour
"""
colour = nord_palette_dark[3]
colours = [colour] * len(list(graph.graph.edges))
colours: list[alias.Colour | alias.Colours] = [colour] * len(
list(graph.graph.edges)
)

return colours


def default_edge_style() -> alias.Style:
"""
Return the default edge style
"""
return "solid"


def default_node_edge_colours(
graph: SequenceGraph | PathwayGraph | PathwayMap,
) -> Colours:
) -> alias.Colours:
"""
For each edge in the graph, return a colour
"""
Expand All @@ -110,25 +116,32 @@ def default_node_edge_colours(
return colours


def default_node_colour() -> Colour:
def default_node_colour() -> alias.Colour:
"""
Return the default node colour
"""
return nord_palette_dark[3]


def default_label_colour() -> Colour:
def default_node_style() -> alias.FillStyle:
"""
Return the default node style
"""
return "full"


def default_label_colour() -> alias.Colour:
"""
Return the default label colour
"""
return nord_palette_dark[0]


def default_action_colours(nr_actions: int) -> Colours:
def default_action_colours(nr_actions: int) -> alias.Colours:
"""
For each action, return a colour
"""
colours: Colours = []
colours: alias.Colours = []

while len(colours) < nr_actions:
# Append the whole palette as many times as needed
Expand All @@ -138,7 +151,7 @@ def default_action_colours(nr_actions: int) -> Colours:
return colours[:nr_actions]


def rgba_to_hex(colour: Colour) -> str:
def rgba_to_hex(colour: alias.Colour) -> str:
"""
Return the hex representation of the colour in RGBA representation
"""
Expand All @@ -151,7 +164,7 @@ def rgba_to_hex(colour: Colour) -> str:
return f"#{a:02x}{r:02x}{g:02x}{b:02x}"


def hex_to_rgba(colour: str) -> Colour:
def hex_to_rgba(colour: str) -> alias.Colour:
"""
Return the RGBA representation of the colour in hex representation
"""
Expand Down
19 changes: 12 additions & 7 deletions source/package/adaptation_pathways/plot/pathway_graph/colour.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
from ...graph import PathwayGraph
from ...graph.node import ActionConversion, ActionPeriod
from .. import alias
from ..colour import (
Colour,
Colours,
PlotColours,
default_edge_colours,
default_edge_style,
default_label_colour,
default_node_edge_colours,
default_node_style,
default_nominal_palette,
nord_palette_light,
)


def colour_by_node(
graph: PathwayGraph, colour_by_action_name: dict[str, Colour]
) -> Colours:
graph: PathwayGraph, colour_by_action_name: dict[str, alias.Colour]
) -> list[alias.Colour | alias.Colours]:
# pylint: disable=redefined-outer-name
colours = []
colours: list[alias.Colour | alias.Colours] = []
conversion_colour = nord_palette_light[0]

# Use the same colour for conversions
Expand All @@ -31,7 +32,9 @@ def colour_by_node(
return colours


def colour_by_action_name(graph: PathwayGraph, palette: Colours) -> dict[str, Colour]:
def colour_by_action_name(
graph: PathwayGraph, palette: alias.Colours
) -> dict[str, alias.Colour]:
palette_size = len(palette)
result = {}
idx = 0
Expand All @@ -46,7 +49,7 @@ def colour_by_action_name(graph: PathwayGraph, palette: Colours) -> dict[str, Co
return result


def default_node_colours(graph: PathwayGraph) -> Colours:
def default_node_colours(graph: PathwayGraph) -> list[alias.Colour | alias.Colours]:
colour_by_action_name_ = (
graph.graph.graph["colour_by_action_name"]
if "colour_by_action_name" in graph.graph.graph
Expand All @@ -59,7 +62,9 @@ def default_node_colours(graph: PathwayGraph) -> Colours:
def default_colours(pathway_graph: PathwayGraph) -> PlotColours:
return PlotColours(
default_node_colours(pathway_graph),
default_node_style(),
default_edge_colours(pathway_graph),
default_edge_style(),
default_node_edge_colours(pathway_graph),
default_label_colour(),
)
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

from .classic import plot as plot_classic_pathway_map
from .colour import edge_colours as pathway_map_edge_colours
from .colour import edge_styles as pathway_map_edge_styles
from .colour import node_colours as pathway_map_node_colours
from .colour import node_styles as pathway_map_node_styles
from .default import plot as plot_default_pathway_map
from .plot import PathwayMapLayout, plot_pathway_map
Loading