finish mov_avg

This commit is contained in:
2025-04-25 19:49:46 +02:00
parent 58ebddcd48
commit a7091af1b2
5 changed files with 58 additions and 9 deletions

View File

@@ -46,6 +46,8 @@ class FilterDevApp(tk.Tk):
self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH) self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH)
NavigationToolbar2Tk(self.canvas, self.frame) NavigationToolbar2Tk(self.canvas, self.frame)
self.focus_force()
def update_plot(self): def update_plot(self):
if self.filter is None: if self.filter is None:
return return

View File

@@ -3,4 +3,11 @@ SERVICE_UUID = "9f0dfdb2-e978-494c-8f15-68dbe8d28672"
MILLIS_UUID = "abb92561-a809-453c-8c7c-71d3fff5b86e" MILLIS_UUID = "abb92561-a809-453c-8c7c-71d3fff5b86e"
WEIGHT_UUID = "123e4567-e89b-12d3-a456-426614174000" WEIGHT_UUID = "123e4567-e89b-12d3-a456-426614174000"
DEFAULT_CALIB = 307333.83 DEFAULT_CALIB = 307333.83
MOV_AVG_DEFAULTS = {
"window_size": 10,
"decimals": 1,
"reset_threshold": 0.5,
"ignore_samples": 2
}

View File

@@ -33,7 +33,7 @@ class Filter:
calib_factor = 100. / float(self.calib_entry.get()) calib_factor = 100. / float(self.calib_entry.get())
df = self.device.data df = self.device.data
df = df[df['weights'] < 10e9] df = df[df['weights'] < 10e8]
df['timestamps'] -= df['timestamps'].min() df['timestamps'] -= df['timestamps'].min()
df['filtered'], df['filtered_calib'] = self.filter(df, calib_factor) df['filtered'], df['filtered_calib'] = self.filter(df, calib_factor)

View File

@@ -1,21 +1,58 @@
from tkinter import ttk from statistics import mean
import pandas as pd import pandas as pd
from .base import Filter from .base import Filter
from ..gui import Slider from ..gui import Slider
from ..config import MOV_AVG_DEFAULTS
class MovAvg(Filter): class MovAvg(Filter):
def init_params(self, toolbar): def init_params(self, toolbar):
self.param_map = { self.param_map = {
"window_size": Slider(toolbar, "Window Size", 1, 100, 10, self.callback), "window_size": Slider(toolbar, "Window Size", 1, 100,
"decimals": Slider(toolbar, "Decimals", 1, 5, 1, self.callback), MOV_AVG_DEFAULTS['window_size'],
# "reset_threshold": Slider(self.toolbar, "Reset Threshold", 0.001, 0.1, 0.1, self.update), 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: def filter(self, df: pd.DataFrame, calib_factor: float) -> pd.Series:
params = self._get_params() 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'])) mov_avg_calib = (mov_avg * calib_factor).round(int(params['decimals']))
return mov_avg, mov_avg_calib return mov_avg, mov_avg_calib

View File

@@ -6,8 +6,10 @@ class Slider:
label_text, label_text,
from_, to, from_, to,
initial_value, initial_value,
command): command,
dtype=int):
self.command = command self.command = command
self.dtype = dtype
self.label = ttk.Label(parent, text=f"{label_text}: {int(initial_value)}") self.label = ttk.Label(parent, text=f"{label_text}: {int(initial_value)}")
@@ -16,7 +18,8 @@ class Slider:
def update(self, event=None): def update(self, event=None):
value = self.slider.get() 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() self.command()
def get_value(self): def get_value(self):