Skip to content
Snippets Groups Projects
Commit e1a6bfb4 authored by Oscar Gustafsson's avatar Oscar Gustafsson :bicyclist:
Browse files

Enable configuration of aspects ratios in scheduler GUI

parent b2625bbe
No related branches found
No related tags found
1 merge request!145Enable configuration of aspects ratios in scheduler GUI
Pipeline #88643 passed
...@@ -460,7 +460,11 @@ class Schedule: ...@@ -460,7 +460,11 @@ class Schedule:
) )
return ret return ret
def _get_y_position(self, graph_id): def _get_y_position(
self, graph_id, operation_height=1.0, operation_gap=None
):
if operation_gap is None:
operation_gap = OPERATION_GAP
y_location = self._y_locations[graph_id] y_location = self._y_locations[graph_id]
if y_location == None: if y_location == None:
# Assign the lowest row number not yet in use # Assign the lowest row number not yet in use
...@@ -470,9 +474,9 @@ class Schedule: ...@@ -470,9 +474,9 @@ class Schedule:
possible = set(range(len(self._start_times))) - used possible = set(range(len(self._start_times))) - used
y_location = min(possible) y_location = min(possible)
self._y_locations[graph_id] = y_location self._y_locations[graph_id] = y_location
return OPERATION_GAP + y_location * (1 + OPERATION_GAP) return operation_gap + y_location * (operation_height + operation_gap)
def _plot_schedule(self, ax): def _plot_schedule(self, ax, operation_gap=None):
line_cache = [] line_cache = []
def _draw_arrow(start, end, name="", laps=0): def _draw_arrow(start, end, name="", laps=0):
...@@ -570,7 +574,7 @@ class Schedule: ...@@ -570,7 +574,7 @@ class Schedule:
ax.set_axisbelow(True) ax.set_axisbelow(True)
ax.grid() ax.grid()
for graph_id, op_start_time in self._start_times.items(): for graph_id, op_start_time in self._start_times.items():
ypos = -self._get_y_position(graph_id) ypos = -self._get_y_position(graph_id, operation_gap=operation_gap)
op = self._sfg.find_by_id(graph_id) op = self._sfg.find_by_id(graph_id)
# Rewrite to make better use of NumPy # Rewrite to make better use of NumPy
latency_coords, execution_time_coords = op.get_plot_coordinates() latency_coords, execution_time_coords = op.get_plot_coordinates()
...@@ -596,13 +600,17 @@ class Schedule: ...@@ -596,13 +600,17 @@ class Schedule:
for graph_id, op_start_time in self._start_times.items(): for graph_id, op_start_time in self._start_times.items():
op = self._sfg.find_by_id(graph_id) op = self._sfg.find_by_id(graph_id)
_, out_coords = op.get_io_coordinates() _, out_coords = op.get_io_coordinates()
source_ypos = -self._get_y_position(graph_id) source_ypos = -self._get_y_position(
graph_id, operation_gap=operation_gap
)
for output_port in op.outputs: for output_port in op.outputs:
for output_signal in output_port.signals: for output_signal in output_port.signals:
dest_op = output_signal.destination.operation dest_op = output_signal.destination.operation
dest_start_time = self._start_times[dest_op.graph_id] dest_start_time = self._start_times[dest_op.graph_id]
dest_ypos = -self._get_y_position(dest_op.graph_id) dest_ypos = -self._get_y_position(
dest_op.graph_id, operation_gap=operation_gap
)
( (
dest_in_coords, dest_in_coords,
_, _,
...@@ -623,7 +631,9 @@ class Schedule: ...@@ -623,7 +631,9 @@ class Schedule:
# Get operation with maximum position # Get operation with maximum position
max_pos_graph_id = max(self._y_locations, key=self._y_locations.get) max_pos_graph_id = max(self._y_locations, key=self._y_locations.get)
yposmin = -self._get_y_position(max_pos_graph_id) - OPERATION_GAP yposmin = -self._get_y_position(
max_pos_graph_id, operation_gap=operation_gap
) - (OPERATION_GAP if operation_gap is None else operation_gap)
ax.axis([-1, self._schedule_time + 1, yposmin, 1]) ax.axis([-1, self._schedule_time + 1, yposmin, 1])
ax.xaxis.set_major_locator(MaxNLocator(integer=True)) ax.xaxis.set_major_locator(MaxNLocator(integer=True))
ax.add_line( ax.add_line(
...@@ -641,12 +651,12 @@ class Schedule: ...@@ -641,12 +651,12 @@ class Schedule:
def _reset_y_locations(self): def _reset_y_locations(self):
self._y_locations = self._y_locations = defaultdict(lambda: None) self._y_locations = self._y_locations = defaultdict(lambda: None)
def plot_schedule(self) -> None: def plot_schedule(self, operation_gap=None) -> None:
self._get_figure().show() self._get_figure(operation_gap=operation_gap).show()
def _get_figure(self): def _get_figure(self, operation_gap=None) -> None:
fig, ax = plt.subplots() fig, ax = plt.subplots()
self._plot_schedule(ax) self._plot_schedule(ax, operation_gap=operation_gap)
return fig return fig
def _repr_svg_(self): def _repr_svg_(self):
......
...@@ -14,3 +14,6 @@ OPERATION_LATENCY_INACTIVE = QColor(*LATENCY_COLOR) ...@@ -14,3 +14,6 @@ OPERATION_LATENCY_INACTIVE = QColor(*LATENCY_COLOR)
OPERATION_LATENCY_ACTIVE = QColor(0, 207, 181) OPERATION_LATENCY_ACTIVE = QColor(0, 207, 181)
OPERATION_EXECUTION_TIME_INACTIVE = QColor(*EXECUTION_TIME_COLOR) OPERATION_EXECUTION_TIME_INACTIVE = QColor(*EXECUTION_TIME_COLOR)
OPERATION_EXECUTION_TIME_ACTIVE = QColor(*EXECUTION_TIME_COLOR) OPERATION_EXECUTION_TIME_ACTIVE = QColor(*EXECUTION_TIME_COLOR)
OPERATION_HEIGHT = 0.75
OPERATION_GAP = 0.25
...@@ -14,10 +14,10 @@ from typing import Dict, List, Optional, Set, cast ...@@ -14,10 +14,10 @@ from typing import Dict, List, Optional, Set, cast
from qtpy.QtWidgets import QGraphicsItem, QGraphicsItemGroup from qtpy.QtWidgets import QGraphicsItem, QGraphicsItemGroup
# B-ASIC # B-ASIC
from b_asic._preferences import OPERATION_GAP
from b_asic.operation import Operation from b_asic.operation import Operation
from b_asic.port import InputPort from b_asic.port import InputPort
from b_asic.schedule import Schedule from b_asic.schedule import Schedule
from b_asic.scheduler_gui._preferences import OPERATION_GAP, OPERATION_HEIGHT
from b_asic.scheduler_gui.axes_item import AxesItem from b_asic.scheduler_gui.axes_item import AxesItem
from b_asic.scheduler_gui.operation_item import OperationItem from b_asic.scheduler_gui.operation_item import OperationItem
from b_asic.scheduler_gui.scheduler_event import SchedulerEvent from b_asic.scheduler_gui.scheduler_event import SchedulerEvent
...@@ -31,6 +31,15 @@ class SchedulerItem(SchedulerEvent, QGraphicsItemGroup): # PySide2 / PyQt5 ...@@ -31,6 +31,15 @@ class SchedulerItem(SchedulerEvent, QGraphicsItemGroup): # PySide2 / PyQt5
AxesItem, as well as components from OperationItem. It AxesItem, as well as components from OperationItem. It
also inherits from SchedulerEvent, which acts as a filter for events also inherits from SchedulerEvent, which acts as a filter for events
to OperationItem objects. to OperationItem objects.
Parameters
==========
schedule : Schedule
The Schedule to draw.
parent : QGraphicsItem, optional
The parent. Passed to the constructor of QGraphicsItemGroup
""" """
_axes: Optional[AxesItem] _axes: Optional[AxesItem]
...@@ -42,7 +51,7 @@ class SchedulerItem(SchedulerEvent, QGraphicsItemGroup): # PySide2 / PyQt5 ...@@ -42,7 +51,7 @@ class SchedulerItem(SchedulerEvent, QGraphicsItemGroup): # PySide2 / PyQt5
def __init__( def __init__(
self, schedule: Schedule, parent: Optional[QGraphicsItem] = None self, schedule: Schedule, parent: Optional[QGraphicsItem] = None
): ):
"""Constructs a SchedulerItem. 'parent' is passed to QGraphicsItemGroup's constructor. """Constructs a SchedulerItem. *parent* is passed to QGraphicsItemGroup's constructor.
""" """
# QGraphicsItemGroup.__init__(self, self) # QGraphicsItemGroup.__init__(self, self)
# SchedulerEvent.__init__(self) # SchedulerEvent.__init__(self)
...@@ -60,7 +69,8 @@ class SchedulerItem(SchedulerEvent, QGraphicsItemGroup): # PySide2 / PyQt5 ...@@ -60,7 +69,8 @@ class SchedulerItem(SchedulerEvent, QGraphicsItemGroup): # PySide2 / PyQt5
self._make_graph() self._make_graph()
def clear(self) -> None: def clear(self) -> None:
"""Sets all children's parent to 'None' and delete the children objects. """
Sets all children's parent to 'None' and delete the children objects.
""" """
self._event_items = [] self._event_items = []
for item in self.childItems(): for item in self.childItems():
...@@ -68,8 +78,19 @@ class SchedulerItem(SchedulerEvent, QGraphicsItemGroup): # PySide2 / PyQt5 ...@@ -68,8 +78,19 @@ class SchedulerItem(SchedulerEvent, QGraphicsItemGroup): # PySide2 / PyQt5
del item del item
def is_component_valid_pos(self, item: OperationItem, pos: float) -> bool: def is_component_valid_pos(self, item: OperationItem, pos: float) -> bool:
"""Takes in a component position and returns true if the component's new """
position is valid, false otherwise.""" Takes in a component position and returns true if the component's new
position is valid, false otherwise.
Parameters
==========
item : OperationItem
The component.
pos : float
The x-position to check.
"""
# TODO: implement # TODO: implement
assert self.schedule is not None, "No schedule installed." assert self.schedule is not None, "No schedule installed."
end_time = item.end_time end_time = item.end_time
...@@ -94,24 +115,43 @@ class SchedulerItem(SchedulerEvent, QGraphicsItemGroup): # PySide2 / PyQt5 ...@@ -94,24 +115,43 @@ class SchedulerItem(SchedulerEvent, QGraphicsItemGroup): # PySide2 / PyQt5
return True return True
def _redraw_all_lines(self): def _redraw_all_lines(self) -> None:
"""Redraw all lines in schedule."""
s = set() s = set()
for signals in self._signal_dict.values(): for signals in self._signal_dict.values():
s.update(signals) s.update(signals)
for signal in s: for signal in s:
signal.update_path() signal.update_path()
def _redraw_lines(self, item: OperationItem): def _redraw_lines(self, item: OperationItem) -> None:
"""Update lines connected to *item*.""" """Update lines connected to *item*."""
for signal in self._signal_dict[item]: for signal in self._signal_dict[item]:
signal.update_path() signal.update_path()
def set_item_active(self, item: OperationItem): def set_item_active(self, item: OperationItem) -> None:
"""
Set an item as active, i.e., draw it and connecting signals in special colors.
Parameters
----------
item : OperationItem
The item to set as active.
"""
item.set_active() item.set_active()
for signal in self._signal_dict[item]: for signal in self._signal_dict[item]:
signal.set_active() signal.set_active()
def set_item_inactive(self, item: OperationItem): def set_item_inactive(self, item: OperationItem) -> None:
"""
Set an item as inactive, i.e., draw it and connecting signals in standard colors.
Parameters
----------
item : OperationItem
The item to set as active.
"""
item.set_inactive() item.set_inactive()
for signal in self._signal_dict[item]: for signal in self._signal_dict[item]:
signal.set_inactive() signal.set_inactive()
...@@ -126,8 +166,9 @@ class SchedulerItem(SchedulerEvent, QGraphicsItemGroup): # PySide2 / PyQt5 ...@@ -126,8 +166,9 @@ class SchedulerItem(SchedulerEvent, QGraphicsItemGroup): # PySide2 / PyQt5
self.schedule.move_operation(item.graph_id, move_time) self.schedule.move_operation(item.graph_id, move_time)
def is_valid_delta_time(self, delta_time: int) -> bool: def is_valid_delta_time(self, delta_time: int) -> bool:
"""Takes in a delta time and returns true if the new schedule time is """
valid, false otherwise.""" Takes in a delta time and returns True if the schedule time can be changed by *delta_time*. False otherwise.
"""
# TODO: implement # TODO: implement
# item = self.scene().mouseGrabberItem() # item = self.scene().mouseGrabberItem()
assert self.schedule is not None, "No schedule installed." assert self.schedule is not None, "No schedule installed."
...@@ -137,7 +178,7 @@ class SchedulerItem(SchedulerEvent, QGraphicsItemGroup): # PySide2 / PyQt5 ...@@ -137,7 +178,7 @@ class SchedulerItem(SchedulerEvent, QGraphicsItemGroup): # PySide2 / PyQt5
) )
def set_schedule_time(self, delta_time: int) -> None: def set_schedule_time(self, delta_time: int) -> None:
"""Set the schedule time and redraw the graph.""" """Change the schedule time by *delta_time* and redraw the graph."""
if self._axes is None: if self._axes is None:
raise RuntimeError("No AxesItem!") raise RuntimeError("No AxesItem!")
assert self.schedule is not None, "No schedule installed." assert self.schedule is not None, "No schedule installed."
...@@ -170,7 +211,9 @@ class SchedulerItem(SchedulerEvent, QGraphicsItemGroup): # PySide2 / PyQt5 ...@@ -170,7 +211,9 @@ class SchedulerItem(SchedulerEvent, QGraphicsItemGroup): # PySide2 / PyQt5
op_item = self._operation_items[graph_id] op_item = self._operation_items[graph_id]
op_item.setPos( op_item.setPos(
self._x_axis_indent + self.schedule.start_times[graph_id], self._x_axis_indent + self.schedule.start_times[graph_id],
self.schedule._get_y_position(graph_id), self.schedule._get_y_position(
graph_id, OPERATION_HEIGHT, OPERATION_GAP
),
) )
def _redraw_from_start(self) -> None: def _redraw_from_start(self) -> None:
...@@ -190,21 +233,25 @@ class SchedulerItem(SchedulerEvent, QGraphicsItemGroup): # PySide2 / PyQt5 ...@@ -190,21 +233,25 @@ class SchedulerItem(SchedulerEvent, QGraphicsItemGroup): # PySide2 / PyQt5
max_pos_graph_id = max( max_pos_graph_id = max(
self.schedule._y_locations, key=self.schedule._y_locations.get self.schedule._y_locations, key=self.schedule._y_locations.get
) )
yposmin = self.schedule._get_y_position(max_pos_graph_id) yposmin = self.schedule._get_y_position(
max_pos_graph_id, OPERATION_HEIGHT, OPERATION_GAP
)
if self._axes is None or build: if self._axes is None or build:
self._axes = AxesItem(schedule_time, yposmin + 0.5) self._axes = AxesItem(schedule_time, yposmin + 0.5)
self._event_items += self._axes.event_items self._event_items += self._axes.event_items
else: else:
self._axes.set_height(yposmin + 0.5) self._axes.set_height(yposmin + 0.5)
self._axes.setPos(0, yposmin + 1 + OPERATION_GAP) self._axes.setPos(0, yposmin + OPERATION_HEIGHT + OPERATION_GAP)
def _make_graph(self) -> None: def _make_graph(self) -> None:
"""Makes a new graph out of the stored attributes.""" """Makes a new graph out of the stored attributes."""
# build components # build components
for graph_id in self.schedule.start_times.keys(): for graph_id in self.schedule.start_times.keys():
operation = cast(Operation, self.schedule.sfg.find_by_id(graph_id)) operation = cast(Operation, self.schedule.sfg.find_by_id(graph_id))
component = OperationItem(operation, parent=self) component = OperationItem(
operation, height=OPERATION_HEIGHT, parent=self
)
self._operation_items[graph_id] = component self._operation_items[graph_id] = component
self._set_position(graph_id) self._set_position(graph_id)
self._event_items += component.event_items self._event_items += component.event_items
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment