Skip to content
Draft
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
15 changes: 8 additions & 7 deletions src/ert/ensemble_evaluator/state.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
from typing import Final

COLOR_FAILED: Final = (255, 200, 200)
COLOR_FINISHED: Final = (127, 201, 127)
COLOR_PENDING: Final = (190, 174, 212)
COLOR_RUNNING: Final = (255, 255, 153)
COLOR_UNKNOWN: Final = (128, 128, 128)
COLOR_WAITING: Final = (164, 200, 255)
COLOR_CANCELLED: Final = (235, 242, 246)
COLOR_QUEUED: Final = (183, 191, 199)
COLOR_FAILED: Final = (207, 34, 46)
COLOR_FINISHED: Final = (45, 164, 78)
COLOR_PENDING: Final = COLOR_QUEUED
COLOR_RUNNING: Final = (214, 178, 42)
COLOR_UNKNOWN: Final = (140, 149, 159)
COLOR_WAITING: Final = COLOR_QUEUED
COLOR_CANCELLED: Final = (234, 238, 242)
COLOR_WARNING: Final = (255, 103, 0)

ENSEMBLE_STATE_CANCELLED: Final = "Cancelled"
Expand Down
43 changes: 29 additions & 14 deletions src/ert/gui/experiments/view/progress_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@
QVBoxLayout,
)

from ert.ensemble_evaluator.state import ENSEMBLE_STATE_FAILED, REAL_STATE_TO_COLOR
from ert.ensemble_evaluator.state import (
ENSEMBLE_STATE_FAILED,
REAL_STATE_TO_COLOR,
REALIZATION_STATE_WAITING,
)


class ProgressWidget(QFrame):
Expand All @@ -21,7 +25,7 @@ def __init__(self) -> None:

self._vertical_layout = QVBoxLayout(self)
self._vertical_layout.setContentsMargins(0, 0, 0, 0)
self._vertical_layout.setSpacing(0)
self._vertical_layout.setSpacing(2)
self.setLayout(self._vertical_layout)

self._waiting_progress_bar = QProgressBar(self)
Expand All @@ -39,36 +43,47 @@ def __init__(self) -> None:

self._legend_frame = QFrame(self)
self._vertical_layout.addWidget(self._legend_frame)
self._legend_frame.setFixedHeight(30)
self._legend_frame.setFixedHeight(24)
self._horizontal_legend_layout = QHBoxLayout(self._legend_frame)
self._horizontal_legend_layout.setContentsMargins(0, 0, 0, 0)
self._horizontal_legend_layout.setSpacing(0)
self._horizontal_legend_layout.setSpacing(6)

self._status: dict[str, int] = {}
self._realization_count = 0
self._progress_label_map: dict[str, QLabel] = {}
self._legend_map_text = {}

for state, color in REAL_STATE_TO_COLOR.items():
color_name = QColor(*color).name()

label = QLabel(self)
label.setVisible(False)
label.setObjectName(f"progress_{state}")
label.setStyleSheet(f"background-color : {QColor(*color).name()}")
label.setStyleSheet(f"background-color : {color_name}")
self._progress_label_map[state] = label
self._horizontal_layout.addWidget(label)

label = QLabel(self)
label.setFixedSize(20, 20)
label.setStyleSheet(
f"background-color : {QColor(*color).name()}; border: 1px solid black;"
)
self._horizontal_legend_layout.addWidget(label)
if state == REALIZATION_STATE_WAITING:
marker_style = (
"background-color: transparent;"
"border-radius: 7px;"
f"border: 2px solid {color_name};"
)
else:
marker_style = f"background-color: {color_name};border-radius: 7px;"

legend_marker = QLabel(self)
legend_marker.setFixedSize(14, 14)
legend_marker.setStyleSheet(marker_style)
self._horizontal_legend_layout.addWidget(legend_marker)

label = QLabel(self)
label.setObjectName(f"progress_label_text_{state}")
label.setText(f" {state} ({0}/{0})")
label.setText(f"{state} ({0}/{0})")
self._legend_map_text[state] = label
self._horizontal_legend_layout.addWidget(label)
self._horizontal_legend_layout.addSpacing(16)

self._horizontal_legend_layout.addStretch()

def repaint_components(self) -> None:
if self._realization_count > 0:
Expand All @@ -83,7 +98,7 @@ def repaint_components(self) -> None:

for state, label in self._legend_map_text.items():
label.setText(
f" {state} ({self._status.get(state, 0)}/{self._realization_count})"
f"{state} ({self._status.get(state, 0)}/{self._realization_count})"
)

def stop_waiting_progress_bar(self) -> None:
Expand Down
96 changes: 57 additions & 39 deletions src/ert/gui/experiments/view/realization.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
QModelIndex,
QObject,
QPoint,
QRect,
QSize,
Qt,
)
Expand All @@ -23,12 +24,14 @@
QWidget,
)

from ert.ensemble_evaluator import state
from ert.gui.model.real_list import RealListModel
from ert.gui.model.snapshot import (
CallbackStatusMessageRole,
FMStepColorHint,
MemoryUsageRole,
RealIens,
StatusRole,
)
from ert.shared.status.utils import byte_with_unit

Expand All @@ -40,7 +43,7 @@ def __init__(self, it: int, parent: QWidget | None = None) -> None:
super().__init__(parent)

self._iter = it
self._delegate_size = QSize(90, 90)
self._delegate_size = QSize(70, 70)

self._real_view = QListView(self)
self._real_view.setViewMode(QListView.ViewMode.IconMode)
Expand Down Expand Up @@ -95,66 +98,81 @@ def refresh_current_selection(self) -> None:


class RealizationDelegate(QStyledItemDelegate):
_DOT_DIAMETER = 32
_ARC_MARGIN = 4
_ARC_WIDTH = 5

def __init__(self, size: QSize, parent: QObject) -> None:
super().__init__(parent)
self._size = size
parent.installEventFilter(self)
self.adjustment_point_for_job_rect_margin = QPoint(-20, -20)
self._color_black = QColor(0, 0, 0, 180)
self._color_progress = QColor(50, 173, 230, 200)
self._color_lightgray = QColor("LightGray").lighter(120)
self._pen_black = QPen(self._color_black, 2, Qt.PenStyle.SolidLine)
self.adjustment_point_for_job_rect_margin = QPoint(-12, -12)
self._color_track = QColor(0, 0, 0, 35)
self._pen_outline = QPen(QColor(0, 0, 0, 45), 1, Qt.PenStyle.SolidLine)

@override
def paint(
self, painter: QPainter | None, option: QStyleOptionViewItem, index: QModelIndex
) -> None:
if painter is None:
return
text = index.data(RealIens)
selected_color, finished_count, total_count = tuple(index.data(FMStepColorHint))
realization_label = index.data(RealIens)
status = index.data(StatusRole)
status_color, completed_step_count, total_step_count = tuple(
index.data(FMStepColorHint)
)

painter.save()
painter.setRenderHint(QPainter.RenderHint.TextAntialiasing, True)
painter.setRenderHint(QPainter.RenderHint.Antialiasing, True)

percentage_done = (
100 if total_count < 1 else int((finished_count * 100.0) / total_count)
)

painter.setPen(self._pen_black)
adjusted_rect = option.rect.adjusted(2, 2, -2, -2)

painter.setBrush(
self._color_progress if percentage_done == 100 else self._color_lightgray
if option.state & QStyle.StateFlag.State_Selected:
highlight = QColor(option.palette.color(QPalette.ColorRole.Highlight))
highlight.setAlpha(60)
painter.setPen(Qt.PenStyle.NoPen)
painter.setBrush(highlight)
painter.drawRoundedRect(option.rect.adjusted(2, 2, -2, -2), 6, 6)

status_dot_rect = QRect(
option.rect.center().x() - self._DOT_DIAMETER // 2,
option.rect.top() + 8,
self._DOT_DIAMETER,
self._DOT_DIAMETER,
)
painter.drawEllipse(adjusted_rect)

if 0 < percentage_done < 100:
painter.setBrush(self._color_progress)
painter.drawPie(adjusted_rect, 1440, -int(percentage_done * 57.6))

if option.state & QStyle.StateFlag.State_Selected:
factor: int = (
125
if selected_color.lighter(125).getRgb() != (255, 255, 255, 255)
else 110
if status == state.REALIZATION_STATE_RUNNING and total_step_count > 0:
progress_ring_rect = status_dot_rect.adjusted(
-self._ARC_MARGIN,
-self._ARC_MARGIN,
self._ARC_MARGIN,
self._ARC_MARGIN,
)
painter.setBrush(Qt.BrushStyle.NoBrush)
painter.setPen(QPen(self._color_track, self._ARC_WIDTH))
painter.drawEllipse(progress_ring_rect)
progress_pen = QPen(status_color, self._ARC_WIDTH)
progress_pen.setCapStyle(Qt.PenCapStyle.RoundCap)
painter.setPen(progress_pen)
painter.drawArc(
progress_ring_rect,
90 * 16,
-int(360 * 16 * completed_step_count / total_step_count),
)
selected_color = selected_color.lighter(factor)

painter.setBrush(selected_color)
adjusted_rect = option.rect.adjusted(7, 7, -7, -7)
painter.drawEllipse(adjusted_rect)

font = painter.font()
font.setBold(True)
painter.setFont(font)
painter.setPen(self._pen_outline)
if status == state.REALIZATION_STATE_WAITING:
painter.setBrush(Qt.BrushStyle.NoBrush)
painter.setPen(QPen(status_color, 2))
painter.drawEllipse(status_dot_rect.adjusted(1, 1, -1, -1))
else:
painter.setBrush(status_color)
painter.drawEllipse(status_dot_rect)

adj_rect = option.rect.adjusted(0, 20, 0, 0)
painter.drawText(adj_rect, Qt.AlignmentFlag.AlignHCenter, text)
adj_rect = option.rect.adjusted(0, 45, 0, 0)
painter.setPen(option.palette.color(QPalette.ColorRole.Text))
painter.drawText(
adj_rect, Qt.AlignmentFlag.AlignHCenter, f"{finished_count} / {total_count}"
option.rect.adjusted(0, self._DOT_DIAMETER + 14, 0, 0),
Qt.AlignmentFlag.AlignHCenter,
realization_label,
)

painter.restore()
Expand Down
2 changes: 1 addition & 1 deletion tests/ert/unit_tests/gui/experiments/view/test_legend.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def test_marker_label_text_correct(qtbot, status: dict[str, int]):

assert label_marker
count = status.get(state, 0)
assert f" {state} ({count}/{realization_count})" in label_marker.text()
assert f"{state} ({count}/{realization_count})" in label_marker.text()


@given(
Expand Down
Loading