diff --git a/filter_dev/app.py b/filter_dev/app.py index 6cef755..c7af883 100644 --- a/filter_dev/app.py +++ b/filter_dev/app.py @@ -46,6 +46,8 @@ class FilterDevApp(tk.Tk): self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH) NavigationToolbar2Tk(self.canvas, self.frame) + self.focus_force() + def update_plot(self): if self.filter is None: return diff --git a/filter_dev/config.py b/filter_dev/config.py index 0a8e5c2..ced0964 100644 --- a/filter_dev/config.py +++ b/filter_dev/config.py @@ -3,4 +3,11 @@ SERVICE_UUID = "9f0dfdb2-e978-494c-8f15-68dbe8d28672" MILLIS_UUID = "abb92561-a809-453c-8c7c-71d3fff5b86e" WEIGHT_UUID = "123e4567-e89b-12d3-a456-426614174000" -DEFAULT_CALIB = 307333.83 \ No newline at end of file +DEFAULT_CALIB = 307333.83 + +MOV_AVG_DEFAULTS = { + "window_size": 10, + "decimals": 1, + "reset_threshold": 0.5, + "ignore_samples": 2 +} \ No newline at end of file diff --git a/filter_dev/filter/base.py b/filter_dev/filter/base.py index 3f8d2ae..d857528 100644 --- a/filter_dev/filter/base.py +++ b/filter_dev/filter/base.py @@ -33,7 +33,7 @@ class Filter: calib_factor = 100. / float(self.calib_entry.get()) df = self.device.data - df = df[df['weights'] < 10e9] + df = df[df['weights'] < 10e8] df['timestamps'] -= df['timestamps'].min() df['filtered'], df['filtered_calib'] = self.filter(df, calib_factor) diff --git a/filter_dev/filter/mov_avg.py b/filter_dev/filter/mov_avg.py index 2704984..d4cdffc 100644 --- a/filter_dev/filter/mov_avg.py +++ b/filter_dev/filter/mov_avg.py @@ -1,21 +1,58 @@ -from tkinter import ttk +from statistics import mean import pandas as pd from .base import Filter from ..gui import Slider +from ..config import MOV_AVG_DEFAULTS class MovAvg(Filter): def init_params(self, toolbar): self.param_map = { - "window_size": Slider(toolbar, "Window Size", 1, 100, 10, self.callback), - "decimals": Slider(toolbar, "Decimals", 1, 5, 1, self.callback), - # "reset_threshold": Slider(self.toolbar, "Reset Threshold", 0.001, 0.1, 0.1, self.update), + "window_size": Slider(toolbar, "Window Size", 1, 100, + MOV_AVG_DEFAULTS['window_size'], + self.callback), + "decimals": Slider(toolbar, "Decimals", 1, 5, + MOV_AVG_DEFAULTS['decimals'], + self.callback), + "reset_threshold": Slider(toolbar, "Reset Threshold", 0.01, 1, + MOV_AVG_DEFAULTS['reset_threshold'], + self.callback, float), + "ignore_samples": Slider(toolbar, "Ignore Samples before reset", 1, 10, + MOV_AVG_DEFAULTS['ignore_samples'], + self.callback) } def filter(self, df: pd.DataFrame, calib_factor: float) -> pd.Series: params = self._get_params() - mov_avg = df['weights'].rolling(window=int(params['window_size'])).mean() + reset_threshold = params['reset_threshold'] / calib_factor + + window = [] + mov_avg = [] + ignored_samples = 0 + + for w in df['weights']: + if len(window) < params['window_size']: + window.append(w) + mov_avg.append(mean(window)) + else: + out_of_threshold = abs(mov_avg[-1] - w) > reset_threshold + if out_of_threshold and\ + ignored_samples < params['ignore_samples']: + ignored_samples += 1 + mov_avg.append(mov_avg[-1]) + + elif out_of_threshold: + ignored_samples = 0 + window = [w] + mov_avg.append(w) + + else: + ignored_samples = 0 + window.append(w) + mov_avg.append(mean(window)) + + mov_avg = pd.Series(mov_avg) mov_avg_calib = (mov_avg * calib_factor).round(int(params['decimals'])) return mov_avg, mov_avg_calib diff --git a/filter_dev/gui/slider.py b/filter_dev/gui/slider.py index 498797b..2b25c7d 100644 --- a/filter_dev/gui/slider.py +++ b/filter_dev/gui/slider.py @@ -6,8 +6,10 @@ class Slider: label_text, from_, to, initial_value, - command): + command, + dtype=int): self.command = command + self.dtype = dtype self.label = ttk.Label(parent, text=f"{label_text}: {int(initial_value)}") @@ -16,7 +18,8 @@ class Slider: def update(self, event=None): value = self.slider.get() - self.label.config(text=f"{self.label.cget('text').split(':')[0]}: {int(value)}") + value_str = int(value) if self.dtype == int else f'{value:.02f}' + self.label.config(text=f"{self.label.cget('text').split(':')[0]}: {value_str}") self.command() def get_value(self):