Skip to content

Commit

Permalink
[ref] Updated the dashboard block
Browse files Browse the repository at this point in the history
  • Loading branch information
WeisLeDocto committed Nov 2, 2021
1 parent 8f96e15 commit 3ab8069
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 66 deletions.
152 changes: 88 additions & 64 deletions crappy/blocks/dashboard.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
# coding: utf-8

import threading
from queue import Queue
import numpy as np
from queue import Queue, Empty

from .block import Block
from .._global import OptionalModule
Expand All @@ -14,83 +13,108 @@
Label = OptionalModule("tkinter")


class Dashboard_window:
"""Dashboard class created, is launched in a new thread."""

def __init__(self, labels: list, nb_digits: int, queue: Queue) -> None:
self.root = Tk()
self.root.title('Dashboard')
self.root.resizable(width=False, height=False)
self.nb_digits = nb_digits
self.labels = labels
self.c1 = {}
self.c2 = {}
self.queue = queue
self.stop = False
row = 0
# Creating the first and second column. Second column will be updated.
for label in self.labels:
self.c1[label] = Label(self.root, text=label, borderwidth=15,
font=("Courier bold", 48))
self.c1[label].grid(row=row, column=0)
self.c2[label] = (Label(self.root, text='', borderwidth=15,
font=("Courier bold", 48)))
self.c2[label].grid(row=row, column=1)
row += 1
# Updating the second column until told to stop
while not self.stop:
self.update()

def update(self) -> None:
"""Method to update the output window."""

try:
values = self.queue.get(timeout=0.1)
except Empty:
# Re-looping if nothing to display
return

# Stopping and closing the window
if values == 'stop':
self.stop = True
self.root.destroy()
return
# Updating the display
for label in self.labels:
try:
self.c2[label].configure(text='%.{}f'.format(self.nb_digits) %
values[label])
except KeyError:
# If a wrong label is given it just won't be updated
pass
self.root.update()


class Dashboard(Block):
"""The Dashboard receives data from a :ref:`Link`, and prints it on a new
popped window.
It can receive either a single point, or a :obj:`list` of points. In this
case, the displayed value corresponds to the average of points.
It can only display data coming from one block.
"""

def __init__(self, labels: list = None, nb_digits: int = 3) -> None:
def __init__(self,
labels: list,
nb_digits: int = 2,
verbose: bool = False,
freq: float = 30) -> None:
"""Sets the args and initializes parent class.
Args:
labels (:obj:`list`, optional): Values to plot on the output window. If
:obj:`None`, will plot every data.
labels (:obj:`list`): Values to plot on the output window.
nb_digits (:obj:`int`, optional): Number of decimals to show.
verbose (:obj:`bool`, optional): Display loop frequency ?
freq (:obj:`float`, optional): If set, the block will loop at this
frequency.
"""

super().__init__()
self.verbose = verbose
self.freq = freq
self.labels = labels
self.nb_display_values = len(self.labels) if self.labels else None
self.nb_digits = nb_digits
# global queue
self.queue = Queue()

class Dashboard:
"""Dashboard class created, is launched in a new thread."""

def __init__(self, labels: list, nb_digits: int, queue: Queue) -> None:
self.root = Tk()
self.root.title('Dashboard')
self.root.resizable(width=False, height=False)
self.first_column = labels
self.nb_digits = nb_digits
self.c2 = []
self.queue = queue
# Creating the first and second column. Second column will be updated.
for row_index, first_column in enumerate(self.first_column):
Label(self.root, text=first_column, borderwidth=15,
font=("Courier bold", 48)).grid(row=row_index, column=0)
self.c2.append(
Label(self.root, text='', borderwidth=15, font=("Courier bold", 48)))
self.c2[row_index].grid(row=row_index, column=1)
self.i = 0
while True:
self.update()

def update(self) -> None:
"""Method to update the output window."""

values = self.queue.get()
for row, text in enumerate(values):
self.c2[row].configure(text='%.{}f'.format(self.nb_digits) % text)
self.root.update()

def main(self) -> None:
"""Main loop."""

if not self.labels:
self.labels = list(self.inputs[0].recv(blocking=True).keys())
self.nb_display_values = len(self.labels)
dash_thread = threading.Thread(target=self.Dashboard,
args=(self.labels, self.nb_digits,
self.queue))
dash_thread.daemon = True
dash_thread.start()
list_to_show = []
while True:
data_received = self.inputs[0].recv(blocking=True)
if len(self.labels) == len(data_received):
time = np.mean(list(data_received.values())[0])
values = [np.mean(list(data_received.values())[label]) for label in
range(1, self.nb_display_values)]
list_to_show.append(time)
list_to_show.extend(values)
else:
for label in self.labels:
list_to_show.append(
np.around(np.mean(data_received[label]), self.nb_digits))
self.queue.put(list_to_show)
list_to_show = []
def prepare(self) -> None:
"""Creates the window in a new thread."""

if len(self.inputs) == 0:
raise IOError("No link pointing towards the Dashboard block !")
elif len(self.inputs) > 1:
raise IOError("Too many links pointing towards the Dashboard block !")
self.dash_thread = threading.Thread(target=Dashboard_window,
args=(self.labels, self.nb_digits,
self.queue))
self.dash_thread.start()

def loop(self) -> None:
"""Simply transmits the received data to the thread."""

received_data = [link.recv_last() for link in self.inputs]
if received_data[0] is not None:
self.queue.put_nowait(received_data[0])

def finish(self) -> None:
"""Closes the thread."""
self.queue.put_nowait('stop')
self.dash_thread.join(timeout=0.1)
2 changes: 0 additions & 2 deletions docs/source/features.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ Data plotting
Prints received values in a popup window and with a nicer formatting than
:ref:`Reader`.

.. Important:: This block hasn't been tested on recent releases !

No example featuring a Dashboard block is currently distributed.

- :ref:`Displayer`
Expand Down

0 comments on commit 3ab8069

Please sign in to comment.