From dfcd618cc222851d0033b4e9bce03dc1aab3b32d Mon Sep 17 00:00:00 2001 From: Reznic Date: Fri, 17 Apr 2020 22:24:56 +0300 Subject: [PATCH 01/25] moving clearing stripe --- graphics/graphs.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/graphics/graphs.py b/graphics/graphs.py index 271e0ff..a5f9c0d 100644 --- a/graphics/graphs.py +++ b/graphics/graphs.py @@ -23,7 +23,9 @@ def __init__(self, parent, measurements, height): self.height = height self.width = self.parent.width self.graph_bbox = None + self.graph_clean_bg = None self.graph_bg = None + self.print_index = 0 self.figure = Figure(figsize=(self.width/100.0, self.height/100.0), dpi=100, facecolor=Theme.active().SURFACE) @@ -62,16 +64,22 @@ def render(self): height=self.height, width=self.width) + # self.graph_bbox = self.canvas.figure.bbox self.graph_bbox = self.canvas.figure.bbox + self.graph_clean_bg = self.canvas.copy_from_bbox(self.graph_bbox) self.save_bg() def update(self): - self.figure.canvas.restore_region(self.graph_bg) + x1, y1, x2, y2 = self.graph_bg.get_extents() + self.figure.canvas.restore_region(self.graph_bg, bbox=(x1+100,y1,x1+110,y2), + xy=(self.print_index, y1)) self.graph.set_ydata(self.display_values) self.axis.draw_artist(self.graph) self.figure.canvas.blit(self.graph_bbox) self.figure.canvas.flush_events() + self.print_index += 1 + @property def element(self): return self.canvas From 68db24bb1ff9228e9192cb4c01653494a5fb2ae5 Mon Sep 17 00:00:00 2001 From: Reznic Date: Fri, 17 Apr 2020 23:26:14 +0300 Subject: [PATCH 02/25] first poc --- graphics/graphs.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/graphics/graphs.py b/graphics/graphs.py index a5f9c0d..d14701e 100644 --- a/graphics/graphs.py +++ b/graphics/graphs.py @@ -71,9 +71,14 @@ def render(self): def update(self): x1, y1, x2, y2 = self.graph_bg.get_extents() + print(f"{self.print_index}") + if self.print_index >= 319: + print("------") + self.print_index = 0 self.figure.canvas.restore_region(self.graph_bg, bbox=(x1+100,y1,x1+110,y2), - xy=(self.print_index, y1)) - self.graph.set_ydata(self.display_values) + xy=(self.print_index*3.5, y1)) + self.graph.set_ydata([self.display_values[-3:-1]]) + self.graph.set_xdata(range(self.print_index, self.print_index+2)) self.axis.draw_artist(self.graph) self.figure.canvas.blit(self.graph_bbox) self.figure.canvas.flush_events() From a93e015d75764432842afa568ecc4c98d6bbd7c8 Mon Sep 17 00:00:00 2001 From: Reznic Date: Sun, 19 Apr 2020 22:07:51 +0300 Subject: [PATCH 03/25] improved poc. --- graphics/graphs.py | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/graphics/graphs.py b/graphics/graphs.py index c0cc1ee..396b2ab 100644 --- a/graphics/graphs.py +++ b/graphics/graphs.py @@ -14,6 +14,11 @@ class Graph(object): YLABEL = NotImplemented COLOR = NotImplemented DPI = 100 # pixels per inch + ERASE_GAP = 50 # pixels + CANVAS_WIDTH = 956 # pixel width of canvas + GRAPH_BEGIN_OFFSET = 80 # offset from canvas left corner, to begin of graph + GRAPH_END_OFFSET = 19 # offset from canvas right corner to end of graph + GRAPH_WIDTH = CANVAS_WIDTH - GRAPH_BEGIN_OFFSET - GRAPH_END_OFFSET def __init__(self, parent, measurements, width, height): rcParams.update({'figure.autolayout': True}) @@ -25,7 +30,7 @@ def __init__(self, parent, measurements, width, height): self.width = width self.graph_bbox = None self.graph_clean_bg = None - self.graph_bg = None + self.eraser_bg = None self.print_index = 0 self.current_min_y, self.current_max_y = self.configured_scale @@ -45,10 +50,12 @@ def __init__(self, parent, measurements, width, height): self.axis.axhline(y=0, color='white', lw=1) # Configure graph - self.display_values = [0] * self.measurements._amount_of_samples_in_graph + self.display_values = [0] * self.GRAPH_WIDTH self.graph, = self.axis.plot( - self.measurements.x_axis, + # self.measurements.x_axis, + range(0, self.GRAPH_WIDTH), self.display_values, + # self.display_values, color=self.COLOR, linewidth=1, animated=True) @@ -60,7 +67,11 @@ def __init__(self, parent, measurements, width, height): def save_bg(self): """Capture the current drawing of graph, and render it as background.""" - self.graph_bg = self.canvas.copy_from_bbox(self.graph_bbox) + x1, y1, x2, y2 = self.graph_clean_bg.get_extents() + + # Capture column of 1 pixel width, from middle of the clean background + bbox = (x1 + 200, y1, x1 + 201, y2) + self.eraser_bg = self.canvas.copy_from_bbox(bbox) def render(self): self.canvas.draw() @@ -72,13 +83,12 @@ def render(self): self.save_bg() def update(self): - x1, y1, x2, y2 = self.graph_bg.get_extents() - print(f"{self.print_index}") - if self.print_index >= 319: - print("------") - self.print_index = 0 - self.figure.canvas.restore_region(self.graph_bg, bbox=(x1+100,y1,x1+110,y2), - xy=(self.print_index*3.5, y1)) + self.print_index %= self.GRAPH_WIDTH + erase_index = ((self.print_index + self.ERASE_GAP) % self.GRAPH_WIDTH) \ + + self.GRAPH_BEGIN_OFFSET + + self.figure.canvas.restore_region(self.eraser_bg, + xy=(erase_index, 0)) self.graph.set_ydata([self.display_values[-3:-1]]) self.graph.set_xdata(range(self.print_index, self.print_index+2)) self.axis.draw_artist(self.graph) @@ -183,8 +193,9 @@ def __init__(self, *args, **kwargs): self.min_threshold = None self.max_threshold = None self.config.pressure_range.observer.subscribe(self, self.update_thresholds) - self.update_thresholds((self.config.pressure_range.min, - self.config.pressure_range.max)) + # Todo: find way to run this at start + # self.update_thresholds((self.config.pressure_range.min, + # self.config.pressure_range.max)) def update_thresholds(self, range): min_value, max_value = range From 905d78834ef60f4a6673325c6d5090cf2c55802e Mon Sep 17 00:00:00 2001 From: Reznic Date: Mon, 20 Apr 2020 10:06:03 +0300 Subject: [PATCH 04/25] works decently. graph width calculated. samples num can change. begin pixel offset still magic constant. not supporting re-rendering. --- graphics/graphs.py | 50 ++++++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/graphics/graphs.py b/graphics/graphs.py index 396b2ab..c56de7d 100644 --- a/graphics/graphs.py +++ b/graphics/graphs.py @@ -1,6 +1,7 @@ from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from matplotlib.figure import Figure from matplotlib import rcParams +from math import ceil from data.configurations import Configurations from graphics.themes import Theme @@ -14,11 +15,8 @@ class Graph(object): YLABEL = NotImplemented COLOR = NotImplemented DPI = 100 # pixels per inch - ERASE_GAP = 50 # pixels - CANVAS_WIDTH = 956 # pixel width of canvas - GRAPH_BEGIN_OFFSET = 80 # offset from canvas left corner, to begin of graph - GRAPH_END_OFFSET = 19 # offset from canvas right corner to end of graph - GRAPH_WIDTH = CANVAS_WIDTH - GRAPH_BEGIN_OFFSET - GRAPH_END_OFFSET + ERASE_GAP = 20 # samples to be cleaned from tail, ahead of new sample print + GRAPH_BEGIN_OFFSET = 80 # pixel offset from canvas edge, to begin of graph def __init__(self, parent, measurements, width, height): rcParams.update({'figure.autolayout': True}) @@ -31,6 +29,7 @@ def __init__(self, parent, measurements, width, height): self.graph_bbox = None self.graph_clean_bg = None self.eraser_bg = None + self.pixels_per_sample = None self.print_index = 0 self.current_min_y, self.current_max_y = self.configured_scale @@ -50,12 +49,11 @@ def __init__(self, parent, measurements, width, height): self.axis.axhline(y=0, color='white', lw=1) # Configure graph - self.display_values = [0] * self.GRAPH_WIDTH + self.samples_width = self.measurements._amount_of_samples_in_graph + self.display_values = [0] * self.samples_width self.graph, = self.axis.plot( - # self.measurements.x_axis, - range(0, self.GRAPH_WIDTH), + self.measurements.x_axis, self.display_values, - # self.display_values, color=self.COLOR, linewidth=1, animated=True) @@ -65,12 +63,21 @@ def __init__(self, parent, measurements, width, height): # Scaling self.graph.axes.set_ylim(*self.configured_scale) + @property + def graph_width(self): + """Return the pixel width of the graph axis.""" + boundaries = self.axis.get_position() * \ + self.axis.get_figure().get_size_inches() * self.DPI + width, height = boundaries[1] - boundaries[0] + return ceil(float(width)) + def save_bg(self): """Capture the current drawing of graph, and render it as background.""" x1, y1, x2, y2 = self.graph_clean_bg.get_extents() - # Capture column of 1 pixel width, from middle of the clean background - bbox = (x1 + 200, y1, x1 + 201, y2) + # Capture column of pixels, from middle of the clean background, + # This column will be pasted cyclically on the graph, to clean it. + bbox = (x1 + 200, y1, ceil(x1 + 200 + self.pixels_per_sample), y2) self.eraser_bg = self.canvas.copy_from_bbox(bbox) def render(self): @@ -80,12 +87,19 @@ def render(self): width=self.width) self.graph_bbox = self.canvas.figure.bbox self.graph_clean_bg = self.canvas.copy_from_bbox(self.graph_bbox) + + self.pixels_per_sample = float(self.graph_width) / self.samples_width + self.save_bg() def update(self): - self.print_index %= self.GRAPH_WIDTH - erase_index = ((self.print_index + self.ERASE_GAP) % self.GRAPH_WIDTH) \ - + self.GRAPH_BEGIN_OFFSET + # print position advances cyclically + self.print_index %= self.samples_width + + # Calculate which pixels to erase + erase_index = \ + int(((self.print_index + self.ERASE_GAP) * self.pixels_per_sample) % self.graph_width \ + + self.GRAPH_BEGIN_OFFSET) + 1 self.figure.canvas.restore_region(self.eraser_bg, xy=(erase_index, 0)) @@ -193,9 +207,6 @@ def __init__(self, *args, **kwargs): self.min_threshold = None self.max_threshold = None self.config.pressure_range.observer.subscribe(self, self.update_thresholds) - # Todo: find way to run this at start - # self.update_thresholds((self.config.pressure_range.min, - # self.config.pressure_range.max)) def update_thresholds(self, range): min_value, max_value = range @@ -213,6 +224,11 @@ def update_thresholds(self, range): self.canvas.draw() self.save_bg() + def render(self): + super().render() + self.update_thresholds((self.config.pressure_range.min, + self.config.pressure_range.max)) + @property def configured_scale(self): return self.config.pressure_y_scale From c2e5f77e9c4900fbf01a3a6b60fb7068c914cc74 Mon Sep 17 00:00:00 2001 From: Reznic Date: Mon, 20 Apr 2020 12:46:01 +0300 Subject: [PATCH 05/25] testing with scatter --- graphics/graphs.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/graphics/graphs.py b/graphics/graphs.py index c56de7d..8be56bf 100644 --- a/graphics/graphs.py +++ b/graphics/graphs.py @@ -20,6 +20,7 @@ class Graph(object): def __init__(self, parent, measurements, width, height): rcParams.update({'figure.autolayout': True}) + rcParams.update({'lines.antialiased': True}) self.parent = parent self.root = parent.element self.measurements = measurements @@ -58,6 +59,8 @@ def __init__(self, parent, measurements, width, height): linewidth=1, animated=True) + self.scat = self.axis.scatter([0], [0], s=1, color="red", animated=True) + self.canvas = FigureCanvasTkAgg(self.figure, master=self.root) # Scaling @@ -103,9 +106,12 @@ def update(self): self.figure.canvas.restore_region(self.eraser_bg, xy=(erase_index, 0)) - self.graph.set_ydata([self.display_values[-3:-1]]) - self.graph.set_xdata(range(self.print_index, self.print_index+2)) + + self.scat.set_offsets([self.print_index+1, self.display_values[-1]]) + self.graph.set_ydata([self.display_values[-2:]]) + self.graph.set_xdata([self.print_index, self.print_index + 1]) self.axis.draw_artist(self.graph) + self.axis.draw_artist(self.scat) self.figure.canvas.blit(self.graph_bbox) self.figure.canvas.flush_events() From 248c9984c5aefb3407bb23af44d29836b2ccec10 Mon Sep 17 00:00:00 2001 From: Reznic Date: Mon, 20 Apr 2020 12:51:29 +0300 Subject: [PATCH 06/25] removed scatter --- graphics/graphs.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/graphics/graphs.py b/graphics/graphs.py index 8be56bf..16af2e9 100644 --- a/graphics/graphs.py +++ b/graphics/graphs.py @@ -59,8 +59,6 @@ def __init__(self, parent, measurements, width, height): linewidth=1, animated=True) - self.scat = self.axis.scatter([0], [0], s=1, color="red", animated=True) - self.canvas = FigureCanvasTkAgg(self.figure, master=self.root) # Scaling @@ -107,11 +105,9 @@ def update(self): self.figure.canvas.restore_region(self.eraser_bg, xy=(erase_index, 0)) - self.scat.set_offsets([self.print_index+1, self.display_values[-1]]) self.graph.set_ydata([self.display_values[-2:]]) self.graph.set_xdata([self.print_index, self.print_index + 1]) self.axis.draw_artist(self.graph) - self.axis.draw_artist(self.scat) self.figure.canvas.blit(self.graph_bbox) self.figure.canvas.flush_events() From e093fff81589739a314c88cced0de64d6ee8a36e Mon Sep 17 00:00:00 2001 From: Reznic Date: Mon, 20 Apr 2020 12:57:03 +0300 Subject: [PATCH 07/25] trying tight layout to solve large margins --- graphics/graphs.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/graphics/graphs.py b/graphics/graphs.py index 16af2e9..4ef2804 100644 --- a/graphics/graphs.py +++ b/graphics/graphs.py @@ -63,6 +63,7 @@ def __init__(self, parent, measurements, width, height): # Scaling self.graph.axes.set_ylim(*self.configured_scale) + self.figure.tight_layout() @property def graph_width(self): @@ -103,7 +104,7 @@ def update(self): + self.GRAPH_BEGIN_OFFSET) + 1 self.figure.canvas.restore_region(self.eraser_bg, - xy=(erase_index, 0)) + xy=(erase_index, -1)) self.graph.set_ydata([self.display_values[-2:]]) self.graph.set_xdata([self.print_index, self.print_index + 1]) From e7d7369508925cd8e62260e2aee7ed11016a522e Mon Sep 17 00:00:00 2001 From: Reznic Date: Mon, 20 Apr 2020 13:06:11 +0300 Subject: [PATCH 08/25] minor adjustments --- graphics/graphs.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/graphics/graphs.py b/graphics/graphs.py index 4ef2804..1844f58 100644 --- a/graphics/graphs.py +++ b/graphics/graphs.py @@ -15,12 +15,11 @@ class Graph(object): YLABEL = NotImplemented COLOR = NotImplemented DPI = 100 # pixels per inch - ERASE_GAP = 20 # samples to be cleaned from tail, ahead of new sample print + ERASE_GAP = 10 # samples to be cleaned from tail, ahead of new sample print GRAPH_BEGIN_OFFSET = 80 # pixel offset from canvas edge, to begin of graph def __init__(self, parent, measurements, width, height): rcParams.update({'figure.autolayout': True}) - rcParams.update({'lines.antialiased': True}) self.parent = parent self.root = parent.element self.measurements = measurements @@ -104,7 +103,7 @@ def update(self): + self.GRAPH_BEGIN_OFFSET) + 1 self.figure.canvas.restore_region(self.eraser_bg, - xy=(erase_index, -1)) + xy=(erase_index, 0)) self.graph.set_ydata([self.display_values[-2:]]) self.graph.set_xdata([self.print_index, self.print_index + 1]) From f096226430678001f9ea05e31e9d456eaf60fa66 Mon Sep 17 00:00:00 2001 From: Reznic Date: Mon, 20 Apr 2020 15:05:49 +0300 Subject: [PATCH 09/25] changed graph values queue to dequeue --- data/measurements.py | 33 ++++++++++++++------------- graphics/graphs.py | 36 ++++++++++++++++++++---------- graphics/panes.py | 15 ------------- tests/unit/graphics/test_graphs.py | 12 +++++----- 4 files changed, 48 insertions(+), 48 deletions(-) diff --git a/data/measurements.py b/data/measurements.py index 518bb96..6dd80f5 100644 --- a/data/measurements.py +++ b/data/measurements.py @@ -1,4 +1,4 @@ -from queue import Queue +from collections import deque from threading import Lock from data.configurations import Configurations @@ -10,10 +10,13 @@ def __init__(self, sample_rate=22): self.expiration_volume = 0 self.avg_insp_volume = 0 self.avg_exp_volume = 0 - self.flow_measurements = Queue(maxsize=40) # TODO: Rename? - self.pressure_measurements = Queue(maxsize=40) # TODO: Rename? self.sample_interval = 1 / sample_rate - self.x_axis = range(0, self._amount_of_samples_in_graph) + self.flow_measurements = deque(maxlen=self.samples_in_graph) # TODO: Rename? + self.pressure_measurements = deque(maxlen=self.samples_in_graph) # TODO: Rename? + for _ in range(self.samples_in_graph): + self.flow_measurements.append(0) + self.pressure_measurements.append(0) + self.x_axis = range(0, self.samples_in_graph) self.intake_peak_flow = 0 self.intake_peak_pressure = 0 self.peep_min_pressure = 0 @@ -35,24 +38,24 @@ def reset(self): def set_flow_value(self, new_value): with self.lock: # pop last item if queue is full - if self.flow_measurements.full(): - self.flow_measurements.get() - self.flow_measurements.put(new_value) + if len(self.flow_measurements) == self.samples_in_graph: + self.flow_measurements.popleft() + self.flow_measurements.append(new_value) def set_pressure_value(self, new_value): with self.lock: # pop last item if queue is full - if self.pressure_measurements.full(): - self.pressure_measurements.get() - self.pressure_measurements.put(new_value) + if len(self.pressure_measurements) == self.samples_in_graph: + self.pressure_measurements.popleft() + self.pressure_measurements.append(new_value) - def get_flow_value(self, new_value): + def get_flow_value(self): with self.lock: - self.flow_measurements.get(new_value) + return self.flow_measurements[-1] - def get_pressure_value(self, new_value): + def get_pressure_value(self): with self.lock: - self.pressure_measurements.get(new_value) + return self.pressure_measurements[-1] def set_intake_peaks(self, flow, pressure, volume): self.intake_peak_flow = flow @@ -66,6 +69,6 @@ def set_battery_percentage(self, percentage): self.battery_percentage = percentage @property - def _amount_of_samples_in_graph(self): + def samples_in_graph(self): config = Configurations.instance() return int(config.graph_seconds / self.sample_interval) diff --git a/graphics/graphs.py b/graphics/graphs.py index 1844f58..0904291 100644 --- a/graphics/graphs.py +++ b/graphics/graphs.py @@ -26,6 +26,7 @@ def __init__(self, parent, measurements, width, height): self.config = Configurations.instance() self.height = height self.width = width + self.graph_width = None self.graph_bbox = None self.graph_clean_bg = None self.eraser_bg = None @@ -49,8 +50,6 @@ def __init__(self, parent, measurements, width, height): self.axis.axhline(y=0, color='white', lw=1) # Configure graph - self.samples_width = self.measurements._amount_of_samples_in_graph - self.display_values = [0] * self.samples_width self.graph, = self.axis.plot( self.measurements.x_axis, self.display_values, @@ -64,8 +63,7 @@ def __init__(self, parent, measurements, width, height): self.graph.axes.set_ylim(*self.configured_scale) self.figure.tight_layout() - @property - def graph_width(self): + def get_graph_width(self): """Return the pixel width of the graph axis.""" boundaries = self.axis.get_position() * \ self.axis.get_figure().get_size_inches() * self.DPI @@ -82,20 +80,25 @@ def save_bg(self): self.eraser_bg = self.canvas.copy_from_bbox(bbox) def render(self): + """Called only once - to render the graph""" self.canvas.draw() self.canvas.get_tk_widget().place(relx=self.RELX, rely=self.RELY, height=self.height, width=self.width) self.graph_bbox = self.canvas.figure.bbox self.graph_clean_bg = self.canvas.copy_from_bbox(self.graph_bbox) - - self.pixels_per_sample = float(self.graph_width) / self.samples_width - + self.graph_width = self.get_graph_width() + self.pixels_per_sample = \ + float(self.graph_width) / self.measurements.samples_in_graph self.save_bg() + def rerender(self): + """Called when graph properties changed, and re-render required.""" + self.render() + def update(self): # print position advances cyclically - self.print_index %= self.samples_width + self.print_index %= self.measurements.samples_in_graph # Calculate which pixels to erase erase_index = \ @@ -105,7 +108,7 @@ def update(self): self.figure.canvas.restore_region(self.eraser_bg, xy=(erase_index, 0)) - self.graph.set_ydata([self.display_values[-2:]]) + self.graph.set_ydata([self.display_values[-2], self.display_values[-1]]) self.graph.set_xdata([self.print_index, self.print_index + 1]) self.axis.draw_artist(self.graph) self.figure.canvas.blit(self.graph_bbox) @@ -121,6 +124,10 @@ def element(self): def configured_scale(self): raise NotImplementedError() + @property + def display_values(self): + raise NotImplementedError() + class FlowGraph(Graph): RELX = 0 @@ -144,6 +151,10 @@ def __init__(self, *args, **kwargs): def configured_scale(self): return self.config.flow_y_scale + @property + def display_values(self): + return self.measurements.flow_measurements + def autoscale(self): """Symmetrically rescale the Y-axis.""" self.current_iteration += 1 @@ -208,7 +219,8 @@ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.min_threshold = None self.max_threshold = None - self.config.pressure_range.observer.subscribe(self, self.update_thresholds) + self.config.pressure_range.observer.subscribe(self, + self.update_thresholds) def update_thresholds(self, range): min_value, max_value = range @@ -236,5 +248,5 @@ def configured_scale(self): return self.config.pressure_y_scale @property - def element(self): - return self.canvas + def display_values(self): + return self.measurements.pressure_measurements diff --git a/graphics/panes.py b/graphics/panes.py index 3b6c814..ce919de 100644 --- a/graphics/panes.py +++ b/graphics/panes.py @@ -104,14 +104,6 @@ def __init__(self, parent, measurements): self.pressure_graph = AirPressureGraph(self, self.measurements, self.width, self.height/2) - def pop_queue_to_list(self, q, lst): - # pops all queue values into list, returns if items appended to queue - had_values = not q.empty() - while not q.empty(): - lst.pop(0) - lst.append(q.get()) - return had_values - @property def element(self): return self.frame @@ -128,13 +120,6 @@ def render(self): def update(self): - # Get measurments from peripherals - - self.pop_queue_to_list(self.measurements.pressure_measurements, - self.pressure_graph.display_values) - self.pop_queue_to_list(self.measurements.flow_measurements, - self.flow_graph.display_values) - for graph in self.graphs: graph.update() diff --git a/tests/unit/graphics/test_graphs.py b/tests/unit/graphics/test_graphs.py index 4f1d361..c737f25 100644 --- a/tests/unit/graphics/test_graphs.py +++ b/tests/unit/graphics/test_graphs.py @@ -91,7 +91,7 @@ def test_graph_symmetrically_autoscales_when_value_exceeds_max(flow_graph: FlowG flow_graph.current_max_y = 10.0 flow_graph.GRAPH_MARGINS = 1.2 - x = flow_graph.measurements._amount_of_samples_in_graph + x = flow_graph.measurements.samples_in_graph flow_graph.display_values = [10] * x flow_graph.display_values[1] += 3 @@ -108,7 +108,7 @@ def test_graph_symmetrically_autoscales_when_value_exceeds_min(flow_graph: FlowG flow_graph.current_max_y = 10.0 flow_graph.GRAPH_MARGINS = 1.2 - x = flow_graph.measurements._amount_of_samples_in_graph + x = flow_graph.measurements.samples_in_graph flow_graph.display_values = [-10] * x flow_graph.display_values[1] -= 3 @@ -126,7 +126,7 @@ def test_loose_graph_behaviour(flow_graph: FlowGraph): flow_graph.current_max_y = 10.0 flow_graph.GRAPH_MARGINS = 1.2 - x = flow_graph.measurements._amount_of_samples_in_graph + x = flow_graph.measurements.samples_in_graph flow_graph.display_values = [-10] * x flow_graph.display_values[1] -= 3 @@ -144,7 +144,7 @@ def test_pressure_graph_doesnt_autoscale(pressure_graph: AirPressureGraph): pressure_graph.current_max_y = 10.0 pressure_graph.GRAPH_MARGINS = 1.2 - x = pressure_graph.measurements._amount_of_samples_in_graph + x = pressure_graph.measurements.samples_in_graph pressure_graph.display_values = [-10] * x pressure_graph.display_values[1] -= 3 @@ -163,7 +163,7 @@ def test_autoscale_can_be_disabled(flow_graph: FlowGraph): flow_graph.current_max_y = 10.0 flow_graph.GRAPH_MARGINS = 1.2 - x = flow_graph.measurements._amount_of_samples_in_graph + x = flow_graph.measurements.samples_in_graph flow_graph.display_values = [-10] * x flow_graph.display_values[1] -= 3 @@ -180,7 +180,7 @@ def test_autoscale_zooms_in(flow_graph: FlowGraph): flow_graph.current_max_y = 10.0 flow_graph.GRAPH_MARGINS = 1.2 - x = flow_graph.measurements._amount_of_samples_in_graph + x = flow_graph.measurements.samples_in_graph flow_graph.display_values = [-10] * x flow_graph.display_values[1] -= 3 From a534bbcf7951229ffa64214d1d7ddc836a6b5ddf Mon Sep 17 00:00:00 2001 From: Reznic Date: Mon, 20 Apr 2020 17:57:18 +0300 Subject: [PATCH 10/25] fixed double printing bug --- graphics/graphs.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/graphics/graphs.py b/graphics/graphs.py index 0904291..890773e 100644 --- a/graphics/graphs.py +++ b/graphics/graphs.py @@ -108,8 +108,11 @@ def update(self): self.figure.canvas.restore_region(self.eraser_bg, xy=(erase_index, 0)) - self.graph.set_ydata([self.display_values[-2], self.display_values[-1]]) + last = self.display_values.popleft() + + self.graph.set_ydata([last, self.display_values[0]]) self.graph.set_xdata([self.print_index, self.print_index + 1]) + self.axis.draw_artist(self.graph) self.figure.canvas.blit(self.graph_bbox) self.figure.canvas.flush_events() From 0ac4c6f5e3cc64dd41f55155b39d80e6414f28c8 Mon Sep 17 00:00:00 2001 From: Reznic Date: Tue, 21 Apr 2020 00:17:58 +0300 Subject: [PATCH 11/25] shit works but with voodoo. fuck my life --- data/measurements.py | 23 +++++++++------------- graphics/graphs.py | 47 +++++++++++++++++++++++++++++++------------- 2 files changed, 42 insertions(+), 28 deletions(-) diff --git a/data/measurements.py b/data/measurements.py index 6dd80f5..37fcb03 100644 --- a/data/measurements.py +++ b/data/measurements.py @@ -11,11 +11,10 @@ def __init__(self, sample_rate=22): self.avg_insp_volume = 0 self.avg_exp_volume = 0 self.sample_interval = 1 / sample_rate - self.flow_measurements = deque(maxlen=self.samples_in_graph) # TODO: Rename? - self.pressure_measurements = deque(maxlen=self.samples_in_graph) # TODO: Rename? - for _ in range(self.samples_in_graph): - self.flow_measurements.append(0) - self.pressure_measurements.append(0) + self.flow_measurements = deque([0] * self.samples_in_graph, + maxlen=self.samples_in_graph) + self.pressure_measurements = deque([0] * self.samples_in_graph, + maxlen=self.samples_in_graph) self.x_axis = range(0, self.samples_in_graph) self.intake_peak_flow = 0 self.intake_peak_pressure = 0 @@ -37,25 +36,19 @@ def reset(self): def set_flow_value(self, new_value): with self.lock: - # pop last item if queue is full - if len(self.flow_measurements) == self.samples_in_graph: - self.flow_measurements.popleft() self.flow_measurements.append(new_value) def set_pressure_value(self, new_value): with self.lock: - # pop last item if queue is full - if len(self.pressure_measurements) == self.samples_in_graph: - self.pressure_measurements.popleft() self.pressure_measurements.append(new_value) def get_flow_value(self): with self.lock: - return self.flow_measurements[-1] + return (self.flow_measurements[-2], self.flow_measurements[-1]) def get_pressure_value(self): with self.lock: - return self.pressure_measurements[-1] + return (self.pressure_measurements[-2], self.pressure_measurements[-1]) def set_intake_peaks(self, flow, pressure, volume): self.intake_peak_flow = flow @@ -71,4 +64,6 @@ def set_battery_percentage(self, percentage): @property def samples_in_graph(self): config = Configurations.instance() - return int(config.graph_seconds / self.sample_interval) + samples_in_graph = int(config.graph_seconds / self.sample_interval) + # samples in graph MUST BE EVEN. Because they are drawn in pairs + return samples_in_graph + (samples_in_graph % 2) diff --git a/graphics/graphs.py b/graphics/graphs.py index 890773e..6819aea 100644 --- a/graphics/graphs.py +++ b/graphics/graphs.py @@ -32,7 +32,8 @@ def __init__(self, parent, measurements, width, height): self.eraser_bg = None self.pixels_per_sample = None self.print_index = 0 - self.current_min_y, self.current_max_y = self.configured_scale + self.draw_batch_size = 2 + self.draw_batch = [] self.figure = Figure(figsize=(self.width/self.DPI, self.height/self.DPI), @@ -60,6 +61,7 @@ def __init__(self, parent, measurements, width, height): self.canvas = FigureCanvasTkAgg(self.figure, master=self.root) # Scaling + self.current_min_y, self.current_max_y = self.configured_scale self.graph.axes.set_ylim(*self.configured_scale) self.figure.tight_layout() @@ -70,13 +72,16 @@ def get_graph_width(self): width, height = boundaries[1] - boundaries[0] return ceil(float(width)) - def save_bg(self): - """Capture the current drawing of graph, and render it as background.""" + def save_eraser_bg(self): + """Capture background for eraser of cyclic graph.""" + # graph boundary points x1, y1, x2, y2 = self.graph_clean_bg.get_extents() # Capture column of pixels, from middle of the clean background, # This column will be pasted cyclically on the graph, to clean it. - bbox = (x1 + 200, y1, ceil(x1 + 200 + self.pixels_per_sample), y2) + capture_offset = x1 + (self.graph_width / 2) + eraser_width = ceil(self.pixels_per_sample * self.draw_batch_size) + bbox = (capture_offset, y1, capture_offset + eraser_width, y2) self.eraser_bg = self.canvas.copy_from_bbox(bbox) def render(self): @@ -90,33 +95,43 @@ def render(self): self.graph_width = self.get_graph_width() self.pixels_per_sample = \ float(self.graph_width) / self.measurements.samples_in_graph - self.save_bg() + self.save_eraser_bg() def rerender(self): """Called when graph properties changed, and re-render required.""" self.render() + # Todo: print entire graph, except erased part def update(self): + self.draw_batch.append(self.display_values[-1]) + if len(self.draw_batch) < self.draw_batch_size: + # Wait for batch to fill, before drawing it + return + # print position advances cyclically self.print_index %= self.measurements.samples_in_graph - # Calculate which pixels to erase + # Calculate pixel offset to erase at erase_index = \ int(((self.print_index + self.ERASE_GAP) * self.pixels_per_sample) % self.graph_width \ - + self.GRAPH_BEGIN_OFFSET) + 1 + + self.GRAPH_BEGIN_OFFSET) + 1 self.figure.canvas.restore_region(self.eraser_bg, xy=(erase_index, 0)) - last = self.display_values.popleft() - - self.graph.set_ydata([last, self.display_values[0]]) - self.graph.set_xdata([self.print_index, self.print_index + 1]) + # xdata = list(range(self.print_index, + # self.print_index + self.draw_batch_size)) + # n = self.measurements.get_flow_value() + # print("-2,-1:" + str(n)) + # print("batch:" + str(self.draw_batch)) + self.graph.set_ydata(self.draw_batch) + self.graph.set_xdata([self.print_index, self.print_index+1]) self.axis.draw_artist(self.graph) self.figure.canvas.blit(self.graph_bbox) self.figure.canvas.flush_events() + self.draw_batch = self.draw_batch[1:] self.print_index += 1 @property @@ -164,8 +179,12 @@ def autoscale(self): self.current_iteration %= max(self.ZOOM_IN_FREQUENCY, self.ZOOM_OUT_FREQUENCY) - new_min_y = min(self.display_values) - new_max_y = max(self.display_values) + if len(self.display_values): + new_min_y = min(self.display_values) + new_max_y = max(self.display_values) + else: + new_min_y = 0 + new_max_y = 0 # Once every calls we want to try and # zoom back-in @@ -239,7 +258,7 @@ def update_thresholds(self, range): self.max_threshold = self.axis.axhline(y=max_value, color='red', lw=1) self.canvas.draw() - self.save_bg() + self.save_eraser_bg() def render(self): super().render() From 0fb504b63cf4a4c23d9de3f4afb20b515be8460b Mon Sep 17 00:00:00 2001 From: Reznic Date: Tue, 21 Apr 2020 01:50:25 +0300 Subject: [PATCH 12/25] solved async sample gui bug --- application.py | 6 ++---- data/measurements.py | 23 ++++------------------- graphics/graphs.py | 6 ++---- 3 files changed, 8 insertions(+), 27 deletions(-) diff --git a/application.py b/application.py index a315464..65dc7a0 100644 --- a/application.py +++ b/application.py @@ -97,12 +97,10 @@ def run(self): try: time_now = time.time() if (time_now - self.last_gui_update_ts) >= self.frame_interval: - self.gui_update() - self.last_gui_update_ts = time_now - - if (time_now - self.last_sample_update_ts) >= self.sample_interval: self.sample() self.last_sample_update_ts = time_now + self.gui_update() + self.last_gui_update_ts = time_now self.arm_wd_event.set() except KeyboardInterrupt: diff --git a/data/measurements.py b/data/measurements.py index 6dd80f5..1a9456a 100644 --- a/data/measurements.py +++ b/data/measurements.py @@ -11,11 +11,10 @@ def __init__(self, sample_rate=22): self.avg_insp_volume = 0 self.avg_exp_volume = 0 self.sample_interval = 1 / sample_rate - self.flow_measurements = deque(maxlen=self.samples_in_graph) # TODO: Rename? - self.pressure_measurements = deque(maxlen=self.samples_in_graph) # TODO: Rename? - for _ in range(self.samples_in_graph): - self.flow_measurements.append(0) - self.pressure_measurements.append(0) + self.flow_measurements = deque([0] * self.samples_in_graph, + maxlen=self.samples_in_graph) + self.pressure_measurements = deque([0] * self.samples_in_graph, + maxlen=self.samples_in_graph) self.x_axis = range(0, self.samples_in_graph) self.intake_peak_flow = 0 self.intake_peak_pressure = 0 @@ -37,26 +36,12 @@ def reset(self): def set_flow_value(self, new_value): with self.lock: - # pop last item if queue is full - if len(self.flow_measurements) == self.samples_in_graph: - self.flow_measurements.popleft() self.flow_measurements.append(new_value) def set_pressure_value(self, new_value): with self.lock: - # pop last item if queue is full - if len(self.pressure_measurements) == self.samples_in_graph: - self.pressure_measurements.popleft() self.pressure_measurements.append(new_value) - def get_flow_value(self): - with self.lock: - return self.flow_measurements[-1] - - def get_pressure_value(self): - with self.lock: - return self.pressure_measurements[-1] - def set_intake_peaks(self, flow, pressure, volume): self.intake_peak_flow = flow self.intake_peak_pressure = pressure diff --git a/graphics/graphs.py b/graphics/graphs.py index 890773e..c08ed95 100644 --- a/graphics/graphs.py +++ b/graphics/graphs.py @@ -52,7 +52,7 @@ def __init__(self, parent, measurements, width, height): # Configure graph self.graph, = self.axis.plot( self.measurements.x_axis, - self.display_values, + [0] * len(self.measurements.x_axis), color=self.COLOR, linewidth=1, animated=True) @@ -108,9 +108,7 @@ def update(self): self.figure.canvas.restore_region(self.eraser_bg, xy=(erase_index, 0)) - last = self.display_values.popleft() - - self.graph.set_ydata([last, self.display_values[0]]) + self.graph.set_ydata([self.display_values[-2], self.display_values[-1]]) self.graph.set_xdata([self.print_index, self.print_index + 1]) self.axis.draw_artist(self.graph) From b2dc0fa693bd09fdab5bed6b9bd4a1c987ff1455 Mon Sep 17 00:00:00 2001 From: Reznic Date: Tue, 21 Apr 2020 16:16:02 +0300 Subject: [PATCH 13/25] almost finished --- data/measurements.py | 4 +-- graphics/graphs.py | 78 ++++++++++++++++++++++++++++++++------------ 2 files changed, 58 insertions(+), 24 deletions(-) diff --git a/data/measurements.py b/data/measurements.py index 37fcb03..6227935 100644 --- a/data/measurements.py +++ b/data/measurements.py @@ -64,6 +64,4 @@ def set_battery_percentage(self, percentage): @property def samples_in_graph(self): config = Configurations.instance() - samples_in_graph = int(config.graph_seconds / self.sample_interval) - # samples in graph MUST BE EVEN. Because they are drawn in pairs - return samples_in_graph + (samples_in_graph % 2) + return int(config.graph_seconds / self.sample_interval) diff --git a/graphics/graphs.py b/graphics/graphs.py index f9f712e..f0ac63f 100644 --- a/graphics/graphs.py +++ b/graphics/graphs.py @@ -16,7 +16,7 @@ class Graph(object): COLOR = NotImplemented DPI = 100 # pixels per inch ERASE_GAP = 10 # samples to be cleaned from tail, ahead of new sample print - GRAPH_BEGIN_OFFSET = 80 # pixel offset from canvas edge, to begin of graph + GRAPH_BEGIN_OFFSET = 83 # pixel offset from canvas edge, to begin of graph def __init__(self, parent, measurements, width, height): rcParams.update({'figure.autolayout': True}) @@ -26,12 +26,18 @@ def __init__(self, parent, measurements, width, height): self.config = Configurations.instance() self.height = height self.width = width + + # pixel width of graph draw area, without axes self.graph_width = None self.graph_bbox = None + # snapshot of graph frame, in clean state self.graph_clean_bg = None + # snapshot of 1 sample-width column, from clean graph self.eraser_bg = None self.pixels_per_sample = None - self.print_index = 0 + # index of last updated sample + self.print_index = -1 + self.erase_index = None self.figure = Figure(figsize=(self.width/self.DPI, self.height/self.DPI), @@ -91,34 +97,64 @@ def render(self): self.graph_bbox = self.canvas.figure.bbox self.graph_clean_bg = self.canvas.copy_from_bbox(self.graph_bbox) self.graph_width = self.get_graph_width() + print(f"begin offset: {self.width - self.graph_width}") self.pixels_per_sample = \ float(self.graph_width) / self.measurements.samples_in_graph self.save_eraser_bg() - def rerender(self): - """Called when graph properties changed, and re-render required.""" + def redraw(self): + """Redraw entire graph. Called when graph properties changed.""" + print_index = self.print_index + 2 + + # Clone and reorder samples list, to match the draw order + recovery_y_values = self.display_values.copy() + recovery_y_values.rotate(print_index) + recovery_y_values = list(recovery_y_values) + + # Ranges of graph parts to redraw + draw_ranges = [] + + if self.print_index < self.erase_index: + # Normal case: during draw cycle + # |~~~ ~~~| + draw_ranges = [(0, print_index), + (self.erase_index+1, self.measurements.samples_in_graph)] + elif self.print_index > self.erase_index: + # Draw cycle at the right edge. started erasing the left edge + # | ~~~~ | + draw_ranges = [(self.erase_index+1, print_index)] + + # Re-render clean graph frame self.render() - # Todo: print entire graph, except erased part + + # Draw all graph parts + for start_index, end_index in draw_ranges: + self.graph.set_ydata(recovery_y_values[start_index:end_index]) + self.graph.set_xdata(self.measurements.x_axis[start_index:end_index]) + self.axis.draw_artist(self.graph) def update(self): - # print position advances cyclically + # drawn sample index advances cyclically + self.print_index += 1 self.print_index %= self.measurements.samples_in_graph # Calculate pixel offset to erase at - erase_index = \ - int(((self.print_index + self.ERASE_GAP) * self.pixels_per_sample) % self.graph_width \ - + self.GRAPH_BEGIN_OFFSET) + 1 + self.erase_index = (self.print_index + self.ERASE_GAP) % \ + self.measurements.samples_in_graph + erase_offset = int(self.erase_index * self.pixels_per_sample) \ + % self.graph_width + self.GRAPH_BEGIN_OFFSET + # Paste eraser column background, to erase tail sample self.figure.canvas.restore_region(self.eraser_bg, - xy=(erase_index, 0)) + xy=(erase_offset, 0)) + # Draw line between 2 most recent samples self.graph.set_ydata([self.display_values[-2], self.display_values[-1]]) self.graph.set_xdata([self.print_index, self.print_index + 1]) self.axis.draw_artist(self.graph) self.figure.canvas.blit(self.graph_bbox) self.figure.canvas.flush_events() - self.print_index += 1 @property def element(self): @@ -183,7 +219,7 @@ def autoscale(self): self.current_min_y, self.current_max_y = original_min, original_max self.graph.axes.set_ylim(self.current_min_y, self.current_max_y) - self.render() + self.redraw() return if self.current_iteration % self.ZOOM_OUT_FREQUENCY != 0: @@ -207,14 +243,13 @@ def autoscale(self): self.graph.axes.set_ylim(self.current_min_y - self.GRAPH_MARGINS, self.current_max_y + self.GRAPH_MARGINS) - self.render() + self.redraw() def update(self): + super().update() if self.config.autoscale: self.autoscale() - super().update() - class AirPressureGraph(Graph): RELX = 0 @@ -230,8 +265,8 @@ def __init__(self, *args, **kwargs): self.config.pressure_range.observer.subscribe(self, self.update_thresholds) - def update_thresholds(self, range): - min_value, max_value = range + def update_thresholds(self, pressure_range): + min_value, max_value = pressure_range if self.min_threshold: self.min_threshold.remove() @@ -243,13 +278,14 @@ def update_thresholds(self, range): # max threshold line self.max_threshold = self.axis.axhline(y=max_value, color='red', lw=1) - self.canvas.draw() - self.save_eraser_bg() + # self.canvas.draw() + # self.save_eraser_bg() + self.redraw() def render(self): super().render() - self.update_thresholds((self.config.pressure_range.min, - self.config.pressure_range.max)) + # self.update_thresholds((self.config.pressure_range.min, + # self.config.pressure_range.max)) @property def configured_scale(self): From 518a243af0a69d23d6d5247e19394a4d972c80cc Mon Sep 17 00:00:00 2001 From: Reznic Date: Tue, 21 Apr 2020 16:43:23 +0300 Subject: [PATCH 14/25] fixed thresholds update on load --- graphics/graphs.py | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/graphics/graphs.py b/graphics/graphs.py index f0ac63f..17c36c5 100644 --- a/graphics/graphs.py +++ b/graphics/graphs.py @@ -89,6 +89,9 @@ def save_eraser_bg(self): self.eraser_bg = self.canvas.copy_from_bbox(bbox) def render(self): + self._redraw_frame() + + def _redraw_frame(self): """Called only once - to render the graph""" self.canvas.draw() self.canvas.get_tk_widget().place(relx=self.RELX, rely=self.RELY, @@ -102,7 +105,7 @@ def render(self): float(self.graph_width) / self.measurements.samples_in_graph self.save_eraser_bg() - def redraw(self): + def redraw_graph(self): """Redraw entire graph. Called when graph properties changed.""" print_index = self.print_index + 2 @@ -124,9 +127,6 @@ def redraw(self): # | ~~~~ | draw_ranges = [(self.erase_index+1, print_index)] - # Re-render clean graph frame - self.render() - # Draw all graph parts for start_index, end_index in draw_ranges: self.graph.set_ydata(recovery_y_values[start_index:end_index]) @@ -219,7 +219,8 @@ def autoscale(self): self.current_min_y, self.current_max_y = original_min, original_max self.graph.axes.set_ylim(self.current_min_y, self.current_max_y) - self.redraw() + self._redraw_frame() + self.redraw_graph() return if self.current_iteration % self.ZOOM_OUT_FREQUENCY != 0: @@ -243,7 +244,8 @@ def autoscale(self): self.graph.axes.set_ylim(self.current_min_y - self.GRAPH_MARGINS, self.current_max_y + self.GRAPH_MARGINS) - self.redraw() + self._redraw_frame() + self.redraw_graph() def update(self): super().update() @@ -265,7 +267,7 @@ def __init__(self, *args, **kwargs): self.config.pressure_range.observer.subscribe(self, self.update_thresholds) - def update_thresholds(self, pressure_range): + def update_thresholds(self, pressure_range, redraw_graph=True): min_value, max_value = pressure_range if self.min_threshold: @@ -278,14 +280,14 @@ def update_thresholds(self, pressure_range): # max threshold line self.max_threshold = self.axis.axhline(y=max_value, color='red', lw=1) - # self.canvas.draw() - # self.save_eraser_bg() - self.redraw() + self._redraw_frame() + if redraw_graph: + self.redraw_graph() def render(self): - super().render() - # self.update_thresholds((self.config.pressure_range.min, - # self.config.pressure_range.max)) + self.update_thresholds((self.config.pressure_range.min, + self.config.pressure_range.max), + redraw_graph=False) @property def configured_scale(self): From f5c827b198260d844450edf5bb79d013d3051deb Mon Sep 17 00:00:00 2001 From: Reznic Date: Tue, 21 Apr 2020 19:38:48 +0300 Subject: [PATCH 15/25] fixed missed erasing bug, by drawing 5 samples after erase index. removed y axis ticks --- graphics/graphs.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/graphics/graphs.py b/graphics/graphs.py index 17c36c5..acbd9d9 100644 --- a/graphics/graphs.py +++ b/graphics/graphs.py @@ -50,6 +50,7 @@ def __init__(self, parent, measurements, width, height): # Calibrate x-axis self.axis.set_xticks([]) self.axis.set_xticklabels([]) + self.axis.tick_params(direction='out', length=0, width=0, colors='w') # Draw X axis self.axis.axhline(y=0, color='white', lw=1) @@ -100,7 +101,6 @@ def _redraw_frame(self): self.graph_bbox = self.canvas.figure.bbox self.graph_clean_bg = self.canvas.copy_from_bbox(self.graph_bbox) self.graph_width = self.get_graph_width() - print(f"begin offset: {self.width - self.graph_width}") self.pixels_per_sample = \ float(self.graph_width) / self.measurements.samples_in_graph self.save_eraser_bg() @@ -121,11 +121,12 @@ def redraw_graph(self): # Normal case: during draw cycle # |~~~ ~~~| draw_ranges = [(0, print_index), - (self.erase_index+1, self.measurements.samples_in_graph)] + (self.erase_index+5, self.measurements.samples_in_graph)] + elif self.print_index > self.erase_index: # Draw cycle at the right edge. started erasing the left edge # | ~~~~ | - draw_ranges = [(self.erase_index+1, print_index)] + draw_ranges = [(self.erase_index+5, print_index)] # Draw all graph parts for start_index, end_index in draw_ranges: From f16498eeb71ec8055260e6590da32c510eb398e4 Mon Sep 17 00:00:00 2001 From: Reznic Date: Tue, 21 Apr 2020 21:43:39 +0300 Subject: [PATCH 16/25] now blitting only 2 columns - drawn and erased. should improve performance --- graphics/graphs.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/graphics/graphs.py b/graphics/graphs.py index acbd9d9..2b54610 100644 --- a/graphics/graphs.py +++ b/graphics/graphs.py @@ -1,6 +1,7 @@ from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from matplotlib.figure import Figure from matplotlib import rcParams +from matplotlib.transforms import Bbox from math import ceil from data.configurations import Configurations @@ -29,6 +30,7 @@ def __init__(self, parent, measurements, width, height): # pixel width of graph draw area, without axes self.graph_width = None + self.graph_height = None self.graph_bbox = None # snapshot of graph frame, in clean state self.graph_clean_bg = None @@ -85,8 +87,9 @@ def save_eraser_bg(self): # Capture column of pixels, from middle of the clean background, # This column will be pasted cyclically on the graph, to clean it. capture_offset = x1 + (self.graph_width / 2) - eraser_width = ceil(self.pixels_per_sample) - bbox = (capture_offset, y1, capture_offset + eraser_width, y2) + self.eraser_width = ceil(self.pixels_per_sample) + self.graph_height = y2 - y1 + bbox = (capture_offset, y1, capture_offset + self.eraser_width, y2) self.eraser_bg = self.canvas.copy_from_bbox(bbox) def render(self): @@ -134,6 +137,8 @@ def redraw_graph(self): self.graph.set_xdata(self.measurements.x_axis[start_index:end_index]) self.axis.draw_artist(self.graph) + self.figure.canvas.blit(self.graph_bbox) + def update(self): # drawn sample index advances cyclically self.print_index += 1 @@ -144,6 +149,8 @@ def update(self): self.measurements.samples_in_graph erase_offset = int(self.erase_index * self.pixels_per_sample) \ % self.graph_width + self.GRAPH_BEGIN_OFFSET + print_offset = int(self.print_index * self.pixels_per_sample) \ + % self.graph_width + self.GRAPH_BEGIN_OFFSET # Paste eraser column background, to erase tail sample self.figure.canvas.restore_region(self.eraser_bg, @@ -154,7 +161,12 @@ def update(self): self.graph.set_xdata([self.print_index, self.print_index + 1]) self.axis.draw_artist(self.graph) - self.figure.canvas.blit(self.graph_bbox) + self.figure.canvas.blit(Bbox.from_bounds(x0=print_offset, y0=0, + width=self.pixels_per_sample, + height=self.graph_height)) + self.figure.canvas.blit(Bbox.from_bounds(x0=erase_offset, y0=0, + width=self.pixels_per_sample, + height=self.graph_height)) self.figure.canvas.flush_events() @property From 458ee67baf3040ea1034b3d0665de8fd4889daa6 Mon Sep 17 00:00:00 2001 From: Reznic Date: Tue, 21 Apr 2020 22:07:32 +0300 Subject: [PATCH 17/25] fixed graph begin offset --- graphics/graphs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphics/graphs.py b/graphics/graphs.py index 2b54610..32790de 100644 --- a/graphics/graphs.py +++ b/graphics/graphs.py @@ -17,7 +17,7 @@ class Graph(object): COLOR = NotImplemented DPI = 100 # pixels per inch ERASE_GAP = 10 # samples to be cleaned from tail, ahead of new sample print - GRAPH_BEGIN_OFFSET = 83 # pixel offset from canvas edge, to begin of graph + GRAPH_BEGIN_OFFSET = 80 # pixel offset from canvas edge, to begin of graph def __init__(self, parent, measurements, width, height): rcParams.update({'figure.autolayout': True}) From f656be6a64f959659fe64026a61f82c84cf4d0e4 Mon Sep 17 00:00:00 2001 From: Reznic Date: Sun, 26 Apr 2020 10:19:26 +0300 Subject: [PATCH 18/25] added documentation lines --- graphics/graphs.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/graphics/graphs.py b/graphics/graphs.py index 32790de..1156ab8 100644 --- a/graphics/graphs.py +++ b/graphics/graphs.py @@ -144,13 +144,13 @@ def update(self): self.print_index += 1 self.print_index %= self.measurements.samples_in_graph - # Calculate pixel offset to erase at + # Calculate pixel offsets to erase and print at self.erase_index = (self.print_index + self.ERASE_GAP) % \ self.measurements.samples_in_graph erase_offset = int(self.erase_index * self.pixels_per_sample) \ % self.graph_width + self.GRAPH_BEGIN_OFFSET print_offset = int(self.print_index * self.pixels_per_sample) \ - % self.graph_width + self.GRAPH_BEGIN_OFFSET + % self.graph_width + self.GRAPH_BEGIN_OFFSET # Paste eraser column background, to erase tail sample self.figure.canvas.restore_region(self.eraser_bg, @@ -159,8 +159,9 @@ def update(self): # Draw line between 2 most recent samples self.graph.set_ydata([self.display_values[-2], self.display_values[-1]]) self.graph.set_xdata([self.print_index, self.print_index + 1]) - self.axis.draw_artist(self.graph) + + # Update screen only in printed column and erased column areas self.figure.canvas.blit(Bbox.from_bounds(x0=print_offset, y0=0, width=self.pixels_per_sample, height=self.graph_height)) From 82f539f2751dcf79623beda02aac190b7ec74644 Mon Sep 17 00:00:00 2001 From: Reznic Date: Sun, 26 Apr 2020 11:12:18 +0300 Subject: [PATCH 19/25] removed unnecessary method --- graphics/graphs.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/graphics/graphs.py b/graphics/graphs.py index 372b7cb..05f83f4 100644 --- a/graphics/graphs.py +++ b/graphics/graphs.py @@ -17,7 +17,7 @@ class Graph(object): COLOR = NotImplemented DPI = 100 # pixels per inch ERASE_GAP = 10 # samples to be cleaned from tail, ahead of new sample print - GRAPH_BEGIN_OFFSET = 72 # pixel offset from canvas edge, to begin of graph + GRAPH_BEGIN_OFFSET = 73 # pixel offset from canvas edge, to begin of graph def __init__(self, parent, measurements, width, height): rcParams.update({'figure.autolayout': True}) @@ -115,10 +115,6 @@ def tick_aligned_format(x, pos): return label - def save_bg(self): - """Capture the current drawing of graph, and render it as background.""" - self.graph_bg = self.canvas.copy_from_bbox(self.graph_bbox) - def render(self): self._redraw_frame() From fcfc068cf9d918fb66f412a53d199cf37497bda1 Mon Sep 17 00:00:00 2001 From: Reznic Date: Sun, 26 Apr 2020 12:08:55 +0300 Subject: [PATCH 20/25] need to fix ut --- data/measurements.py | 11 +++++++---- graphics/graphs.py | 4 ++-- tests/unit/graphics/test_graphs.py | 30 +++++++++++------------------- 3 files changed, 20 insertions(+), 25 deletions(-) diff --git a/data/measurements.py b/data/measurements.py index 6227935..35cceab 100644 --- a/data/measurements.py +++ b/data/measurements.py @@ -11,10 +11,7 @@ def __init__(self, sample_rate=22): self.avg_insp_volume = 0 self.avg_exp_volume = 0 self.sample_interval = 1 / sample_rate - self.flow_measurements = deque([0] * self.samples_in_graph, - maxlen=self.samples_in_graph) - self.pressure_measurements = deque([0] * self.samples_in_graph, - maxlen=self.samples_in_graph) + self.init_samples_queues(0) self.x_axis = range(0, self.samples_in_graph) self.intake_peak_flow = 0 self.intake_peak_pressure = 0 @@ -24,6 +21,12 @@ def __init__(self, sample_rate=22): self.battery_percentage = 0 self.lock = Lock() + def init_samples_queues(self, init_value): + self.flow_measurements = deque([init_value] * self.samples_in_graph, + maxlen=self.samples_in_graph) + self.pressure_measurements = deque([init_value] * self.samples_in_graph, + maxlen=self.samples_in_graph) + def reset(self): self.inspiration_volume = 0 self.expiration_volume = 0 diff --git a/graphics/graphs.py b/graphics/graphs.py index 05f83f4..14aa0f4 100644 --- a/graphics/graphs.py +++ b/graphics/graphs.py @@ -98,9 +98,9 @@ def save_eraser_bg(self): # Capture column of pixels, from middle of the clean background, # This column will be pasted cyclically on the graph, to clean it. capture_offset = x1 + (self.graph_width / 2) - self.eraser_width = ceil(self.pixels_per_sample) + eraser_width = ceil(self.pixels_per_sample) self.graph_height = y2 - y1 - bbox = (capture_offset, y1, capture_offset + self.eraser_width, y2) + bbox = (capture_offset, y1, capture_offset + eraser_width, y2) self.eraser_bg = self.canvas.copy_from_bbox(bbox) @staticmethod diff --git a/tests/unit/graphics/test_graphs.py b/tests/unit/graphics/test_graphs.py index 999855a..75f306b 100644 --- a/tests/unit/graphics/test_graphs.py +++ b/tests/unit/graphics/test_graphs.py @@ -51,6 +51,7 @@ def pressure_graph(measurements) -> AirPressureGraph: graph.figure = MagicMock() graph.config = MagicMock() graph.config.autoscale = True + graph.pixels_per_sample = 4 return graph @@ -69,6 +70,9 @@ def flow_graph(measurements) -> FlowGraph: graph.config = MagicMock() graph.config.autoscale = True graph.config.flow_y_scale = (-10, 10) + + graph.pixels_per_sample = 4 + return graph @@ -91,9 +95,7 @@ def test_graph_symmetrically_autoscales_when_value_exceeds_max(flow_graph: FlowG flow_graph.current_max_y = 10.0 flow_graph.GRAPH_MARGINS = 1.2 - x = flow_graph.measurements.samples_in_graph - - flow_graph.display_values = [10] * x + flow_graph.measurements.init_samples_queues(10) flow_graph.display_values[1] += 3 for i in range(flow_graph.ZOOM_OUT_FREQUENCY): @@ -108,9 +110,7 @@ def test_graph_symmetrically_autoscales_when_value_exceeds_min(flow_graph: FlowG flow_graph.current_max_y = 10.0 flow_graph.GRAPH_MARGINS = 1.2 - x = flow_graph.measurements.samples_in_graph - - flow_graph.display_values = [-10] * x + flow_graph.measurements.init_samples_queues(-10) flow_graph.display_values[1] -= 3 for i in range(flow_graph.ZOOM_OUT_FREQUENCY): @@ -126,9 +126,7 @@ def test_loose_graph_behaviour(flow_graph: FlowGraph): flow_graph.current_max_y = 10.0 flow_graph.GRAPH_MARGINS = 1.2 - x = flow_graph.measurements.samples_in_graph - - flow_graph.display_values = [-10] * x + flow_graph.measurements.init_samples_queues(-10) flow_graph.display_values[1] -= 3 for i in range(flow_graph.ZOOM_OUT_FREQUENCY): @@ -144,9 +142,7 @@ def test_pressure_graph_doesnt_autoscale(pressure_graph: AirPressureGraph): pressure_graph.current_max_y = 10.0 pressure_graph.GRAPH_MARGINS = 1.2 - x = pressure_graph.measurements.samples_in_graph - - pressure_graph.display_values = [-10] * x + pressure_graph.measurements.init_samples_queues(-10) pressure_graph.display_values[1] -= 3 for i in range(2000): @@ -163,9 +159,7 @@ def test_autoscale_can_be_disabled(flow_graph: FlowGraph): flow_graph.current_max_y = 10.0 flow_graph.GRAPH_MARGINS = 1.2 - x = flow_graph.measurements.samples_in_graph - - flow_graph.display_values = [-10] * x + flow_graph.measurements.init_samples_queues(-10) flow_graph.display_values[1] -= 3 for i in range(flow_graph.ZOOM_OUT_FREQUENCY): @@ -180,9 +174,7 @@ def test_autoscale_zooms_in(flow_graph: FlowGraph): flow_graph.current_max_y = 10.0 flow_graph.GRAPH_MARGINS = 1.2 - x = flow_graph.measurements.samples_in_graph - - flow_graph.display_values = [-10] * x + flow_graph.measurements.init_samples_queues(-10) flow_graph.display_values[1] -= 3 for i in range(flow_graph.ZOOM_OUT_FREQUENCY): @@ -191,7 +183,7 @@ def test_autoscale_zooms_in(flow_graph: FlowGraph): assert flow_graph.current_min_y < -10 assert flow_graph.current_max_y > 10 - flow_graph.display_values = [-10] * x + flow_graph.measurements.init_samples_queues(-10) for i in range(flow_graph.ZOOM_IN_FREQUENCY): flow_graph.update() From 1c835ec2ae40843a953603bf8aca34ca26b3c739 Mon Sep 17 00:00:00 2001 From: Reznic Date: Sun, 26 Apr 2020 12:37:24 +0300 Subject: [PATCH 21/25] UT passes! --- tests/unit/graphics/test_graphs.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/unit/graphics/test_graphs.py b/tests/unit/graphics/test_graphs.py index 75f306b..dda7912 100644 --- a/tests/unit/graphics/test_graphs.py +++ b/tests/unit/graphics/test_graphs.py @@ -50,7 +50,11 @@ def pressure_graph(measurements) -> AirPressureGraph: graph.axis = MagicMock() graph.figure = MagicMock() graph.config = MagicMock() + graph.get_graph_width = MagicMock() graph.config.autoscale = True + + graph.graph_width = 200 + graph.graph_height = 100 graph.pixels_per_sample = 4 return graph @@ -68,9 +72,12 @@ def flow_graph(measurements) -> FlowGraph: graph.axis = MagicMock() graph.figure = MagicMock() graph.config = MagicMock() + graph.get_graph_width = MagicMock() graph.config.autoscale = True graph.config.flow_y_scale = (-10, 10) + graph.graph_width = 200 + graph.graph_height = 100 graph.pixels_per_sample = 4 return graph From df515d447fb5bf166ca1c05ffa3c26e1dbc69038 Mon Sep 17 00:00:00 2001 From: Reznic Date: Sun, 26 Apr 2020 12:50:21 +0300 Subject: [PATCH 22/25] fixed another UT --- tests/unit/test_sanity.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/unit/test_sanity.py b/tests/unit/test_sanity.py index f65e8ba..d81120c 100644 --- a/tests/unit/test_sanity.py +++ b/tests/unit/test_sanity.py @@ -45,11 +45,11 @@ def test_sampler_inserts_pressure_measurement_to_store(events, measurements, con timer = driver_factory.acquire_driver("timer") sampler = Sampler(measurements, events, flow_sensor, pressure_sensor, a2d, timer) - assert measurements.pressure_measurements.qsize() == 0 + assert len(measurements.pressure_measurements) == 0 sampler.sampling_iteration() - assert measurements.pressure_measurements.qsize() == 1 + assert len(measurements.pressure_measurements) == 1 sampler.sampling_iteration() - assert measurements.pressure_measurements.qsize() == 2 + assert len(measurements.pressure_measurements) == 2 def test_sampler_alerts_when_pressure_exceeds_maximum(events, measurements, config, driver_factory): From 377e9f2b59d07fb09831fa938c01ad4ee0270b5f Mon Sep 17 00:00:00 2001 From: Reznic Date: Sun, 26 Apr 2020 14:08:56 +0300 Subject: [PATCH 23/25] fixed another shit in UT --- data/measurements.py | 6 +++--- tests/unit/graphics/test_graphs.py | 23 ++++++++++++++++------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/data/measurements.py b/data/measurements.py index 35cceab..30c521d 100644 --- a/data/measurements.py +++ b/data/measurements.py @@ -21,10 +21,10 @@ def __init__(self, sample_rate=22): self.battery_percentage = 0 self.lock = Lock() - def init_samples_queues(self, init_value): - self.flow_measurements = deque([init_value] * self.samples_in_graph, + def init_samples_queues(self, init_value, size=0): + self.flow_measurements = deque([init_value] * size, maxlen=self.samples_in_graph) - self.pressure_measurements = deque([init_value] * self.samples_in_graph, + self.pressure_measurements = deque([init_value] * size, maxlen=self.samples_in_graph) def reset(self): diff --git a/tests/unit/graphics/test_graphs.py b/tests/unit/graphics/test_graphs.py index dda7912..5757a85 100644 --- a/tests/unit/graphics/test_graphs.py +++ b/tests/unit/graphics/test_graphs.py @@ -45,6 +45,7 @@ def pressure_graph(measurements) -> AirPressureGraph: parent = MagicMock() parent.element = root + measurements.init_samples_queues(0, measurements.samples_in_graph) graph = AirPressureGraph(parent=parent, measurements=measurements, width=parent.width, height=parent.height) graph.axis = MagicMock() @@ -67,6 +68,7 @@ def flow_graph(measurements) -> FlowGraph: parent = MagicMock() parent.element = root + measurements.init_samples_queues(0, measurements.samples_in_graph) graph = FlowGraph(parent=parent, measurements=measurements, width=parent.width, height=parent.height) graph.axis = MagicMock() @@ -102,7 +104,8 @@ def test_graph_symmetrically_autoscales_when_value_exceeds_max(flow_graph: FlowG flow_graph.current_max_y = 10.0 flow_graph.GRAPH_MARGINS = 1.2 - flow_graph.measurements.init_samples_queues(10) + flow_graph.measurements.init_samples_queues(10, + flow_graph.measurements.samples_in_graph) flow_graph.display_values[1] += 3 for i in range(flow_graph.ZOOM_OUT_FREQUENCY): @@ -117,7 +120,8 @@ def test_graph_symmetrically_autoscales_when_value_exceeds_min(flow_graph: FlowG flow_graph.current_max_y = 10.0 flow_graph.GRAPH_MARGINS = 1.2 - flow_graph.measurements.init_samples_queues(-10) + flow_graph.measurements.init_samples_queues(-10, + flow_graph.measurements.samples_in_graph) flow_graph.display_values[1] -= 3 for i in range(flow_graph.ZOOM_OUT_FREQUENCY): @@ -133,7 +137,8 @@ def test_loose_graph_behaviour(flow_graph: FlowGraph): flow_graph.current_max_y = 10.0 flow_graph.GRAPH_MARGINS = 1.2 - flow_graph.measurements.init_samples_queues(-10) + flow_graph.measurements.init_samples_queues(-10, + flow_graph.measurements.samples_in_graph) flow_graph.display_values[1] -= 3 for i in range(flow_graph.ZOOM_OUT_FREQUENCY): @@ -149,7 +154,8 @@ def test_pressure_graph_doesnt_autoscale(pressure_graph: AirPressureGraph): pressure_graph.current_max_y = 10.0 pressure_graph.GRAPH_MARGINS = 1.2 - pressure_graph.measurements.init_samples_queues(-10) + pressure_graph.measurements.init_samples_queues(-10, + pressure_graph.measurements.samples_in_graph) pressure_graph.display_values[1] -= 3 for i in range(2000): @@ -166,7 +172,8 @@ def test_autoscale_can_be_disabled(flow_graph: FlowGraph): flow_graph.current_max_y = 10.0 flow_graph.GRAPH_MARGINS = 1.2 - flow_graph.measurements.init_samples_queues(-10) + flow_graph.measurements.init_samples_queues(-10, + flow_graph.measurements.samples_in_graph) flow_graph.display_values[1] -= 3 for i in range(flow_graph.ZOOM_OUT_FREQUENCY): @@ -181,7 +188,8 @@ def test_autoscale_zooms_in(flow_graph: FlowGraph): flow_graph.current_max_y = 10.0 flow_graph.GRAPH_MARGINS = 1.2 - flow_graph.measurements.init_samples_queues(-10) + flow_graph.measurements.init_samples_queues(-10, + flow_graph.measurements.samples_in_graph) flow_graph.display_values[1] -= 3 for i in range(flow_graph.ZOOM_OUT_FREQUENCY): @@ -190,7 +198,8 @@ def test_autoscale_zooms_in(flow_graph: FlowGraph): assert flow_graph.current_min_y < -10 assert flow_graph.current_max_y > 10 - flow_graph.measurements.init_samples_queues(-10) + flow_graph.measurements.init_samples_queues(-10, + flow_graph.measurements.samples_in_graph) for i in range(flow_graph.ZOOM_IN_FREQUENCY): flow_graph.update() From 63a1f3429ee9459a498439e3534edbaa19e2fe4b Mon Sep 17 00:00:00 2001 From: Reznic Date: Sun, 26 Apr 2020 14:40:05 +0300 Subject: [PATCH 24/25] hopefully all ut will pass now Amengit add -u! --- data/measurements.py | 4 +++- tests/unit/graphics/test_graphs.py | 25 +++++++++---------------- tests/unit/test_sanity.py | 4 +++- 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/data/measurements.py b/data/measurements.py index 30c521d..aff524e 100644 --- a/data/measurements.py +++ b/data/measurements.py @@ -21,7 +21,9 @@ def __init__(self, sample_rate=22): self.battery_percentage = 0 self.lock = Lock() - def init_samples_queues(self, init_value, size=0): + def init_samples_queues(self, init_value, size=None): + if size is None: + size = self.samples_in_graph self.flow_measurements = deque([init_value] * size, maxlen=self.samples_in_graph) self.pressure_measurements = deque([init_value] * size, diff --git a/tests/unit/graphics/test_graphs.py b/tests/unit/graphics/test_graphs.py index 5757a85..7724e31 100644 --- a/tests/unit/graphics/test_graphs.py +++ b/tests/unit/graphics/test_graphs.py @@ -45,7 +45,7 @@ def pressure_graph(measurements) -> AirPressureGraph: parent = MagicMock() parent.element = root - measurements.init_samples_queues(0, measurements.samples_in_graph) + measurements.init_samples_queues(0) graph = AirPressureGraph(parent=parent, measurements=measurements, width=parent.width, height=parent.height) graph.axis = MagicMock() @@ -68,7 +68,7 @@ def flow_graph(measurements) -> FlowGraph: parent = MagicMock() parent.element = root - measurements.init_samples_queues(0, measurements.samples_in_graph) + measurements.init_samples_queues(0) graph = FlowGraph(parent=parent, measurements=measurements, width=parent.width, height=parent.height) graph.axis = MagicMock() @@ -104,8 +104,7 @@ def test_graph_symmetrically_autoscales_when_value_exceeds_max(flow_graph: FlowG flow_graph.current_max_y = 10.0 flow_graph.GRAPH_MARGINS = 1.2 - flow_graph.measurements.init_samples_queues(10, - flow_graph.measurements.samples_in_graph) + flow_graph.measurements.init_samples_queues(10) flow_graph.display_values[1] += 3 for i in range(flow_graph.ZOOM_OUT_FREQUENCY): @@ -120,8 +119,7 @@ def test_graph_symmetrically_autoscales_when_value_exceeds_min(flow_graph: FlowG flow_graph.current_max_y = 10.0 flow_graph.GRAPH_MARGINS = 1.2 - flow_graph.measurements.init_samples_queues(-10, - flow_graph.measurements.samples_in_graph) + flow_graph.measurements.init_samples_queues(-10) flow_graph.display_values[1] -= 3 for i in range(flow_graph.ZOOM_OUT_FREQUENCY): @@ -137,8 +135,7 @@ def test_loose_graph_behaviour(flow_graph: FlowGraph): flow_graph.current_max_y = 10.0 flow_graph.GRAPH_MARGINS = 1.2 - flow_graph.measurements.init_samples_queues(-10, - flow_graph.measurements.samples_in_graph) + flow_graph.measurements.init_samples_queues(-10) flow_graph.display_values[1] -= 3 for i in range(flow_graph.ZOOM_OUT_FREQUENCY): @@ -154,8 +151,7 @@ def test_pressure_graph_doesnt_autoscale(pressure_graph: AirPressureGraph): pressure_graph.current_max_y = 10.0 pressure_graph.GRAPH_MARGINS = 1.2 - pressure_graph.measurements.init_samples_queues(-10, - pressure_graph.measurements.samples_in_graph) + pressure_graph.measurements.init_samples_queues(-10) pressure_graph.display_values[1] -= 3 for i in range(2000): @@ -172,8 +168,7 @@ def test_autoscale_can_be_disabled(flow_graph: FlowGraph): flow_graph.current_max_y = 10.0 flow_graph.GRAPH_MARGINS = 1.2 - flow_graph.measurements.init_samples_queues(-10, - flow_graph.measurements.samples_in_graph) + flow_graph.measurements.init_samples_queues(-10) flow_graph.display_values[1] -= 3 for i in range(flow_graph.ZOOM_OUT_FREQUENCY): @@ -188,8 +183,7 @@ def test_autoscale_zooms_in(flow_graph: FlowGraph): flow_graph.current_max_y = 10.0 flow_graph.GRAPH_MARGINS = 1.2 - flow_graph.measurements.init_samples_queues(-10, - flow_graph.measurements.samples_in_graph) + flow_graph.measurements.init_samples_queues(-10) flow_graph.display_values[1] -= 3 for i in range(flow_graph.ZOOM_OUT_FREQUENCY): @@ -198,8 +192,7 @@ def test_autoscale_zooms_in(flow_graph: FlowGraph): assert flow_graph.current_min_y < -10 assert flow_graph.current_max_y > 10 - flow_graph.measurements.init_samples_queues(-10, - flow_graph.measurements.samples_in_graph) + flow_graph.measurements.init_samples_queues(-10) for i in range(flow_graph.ZOOM_IN_FREQUENCY): flow_graph.update() diff --git a/tests/unit/test_sanity.py b/tests/unit/test_sanity.py index d81120c..b7f881f 100644 --- a/tests/unit/test_sanity.py +++ b/tests/unit/test_sanity.py @@ -30,7 +30,9 @@ def config(): @pytest.fixture def measurements(): - return Measurements() + measurements = Measurements() + measurements.init_samples_queues(0, size=0) + return measurements @pytest.fixture From 9154db2a6ee9473eaa432a525e981b48e960f232 Mon Sep 17 00:00:00 2001 From: Reznic Date: Sun, 26 Apr 2020 15:07:10 +0300 Subject: [PATCH 25/25] decreased graph begin offset --- graphics/graphs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphics/graphs.py b/graphics/graphs.py index 14aa0f4..2c6e914 100644 --- a/graphics/graphs.py +++ b/graphics/graphs.py @@ -17,7 +17,7 @@ class Graph(object): COLOR = NotImplemented DPI = 100 # pixels per inch ERASE_GAP = 10 # samples to be cleaned from tail, ahead of new sample print - GRAPH_BEGIN_OFFSET = 73 # pixel offset from canvas edge, to begin of graph + GRAPH_BEGIN_OFFSET = 70 # pixel offset from canvas edge, to begin of graph def __init__(self, parent, measurements, width, height): rcParams.update({'figure.autolayout': True})