Skip to content

Commit

Permalink
update release notes & screenshot
Browse files Browse the repository at this point in the history
  • Loading branch information
semuadmin committed Nov 7, 2024
1 parent 1751ffa commit 95971c3
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 31 deletions.
1 change: 1 addition & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

ENHANCEMENTS:

1. Further enhancements to scatterplot widget; add autorange, right-click to set fixed ref position, standard deviation in addition to average lat/lon, improved font scaling

### RELEASE 1.4.26

Expand Down
Binary file modified images/scatterplot_widget.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,12 @@ profile = "black"
exclude_dirs = ["docs", "examples", "tests"]
skips = [
"B104",
"B311",
"B318",
"B404",
"B408",
"B603",
] # bind 0.0.0.0; minidom; subroutine
] # bind 0.0.0.0; randrange; minidom; subroutine

[tool.pylint]
jobs = 0
Expand Down
84 changes: 63 additions & 21 deletions src/pygpsclient/scatter_frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,23 +37,27 @@
)

try:
from statistics import pstdev
from statistics import stdev

HASSTATS = True
except (ImportError, ModuleNotFoundError):
HASSTATS = False

from random import randrange

from pygpsclient.globals import BGCOL, FGCOL, SQRT2, WIDGETU2, Area, Point
from pygpsclient.helpers import get_point_at_vector, in_bounds
from pygpsclient.skyview_frame import Canvas

MAXPOINTS = 100000 # equivalent to roughly 24 hours of data or 4.5MB
AVG = "avg"
CTRAVG = "Average"
CTRFIX = "Fixed"
CRTS = (CTRAVG, CTRFIX)
PNTCOL = "orange"
FIXCOL = "green2"
AVG = "avg"
PNTCOL = "orange"
CULLMID = True # whether to cull random points from middle of array
FIXINAUTO = False # whether to include fixed ref point in autorange
MAXPOINTS = 5000


class ScatterViewFrame(Frame):
Expand Down Expand Up @@ -190,6 +194,10 @@ def _attach_events(self):
self.canvas.bind("<Button-3>", self._on_recenter) # win
self.canvas.bind("<MouseWheel>", self._on_zoom)
self._scale.trace_add("write", self._on_rescale)
self._autorange.trace_add("write", self._on_save_settings)
self._centermode.trace_add("write", self._on_save_settings)
self._reflat.trace_add("write", self._on_save_settings)
self._reflon.trace_add("write", self._on_save_settings)

def _on_zoom(self, event):
"""
Expand All @@ -212,6 +220,7 @@ def _on_rescale(self, var, index, mode): # pylint: disable=unused-argument
Rescale widget.
"""

self._on_save_settings(var, index, mode)
self._on_resize(None)

def _on_resize(self, event): # pylint: disable=unused-argument
Expand Down Expand Up @@ -250,6 +259,21 @@ def _on_clear(self, event): # pylint: disable=unused-argument
self._points = []
self._init_frame()

def _on_save_settings(self, var, index, mode): # pylint: disable=unused-argument)
"""
Save current settings to saved app config dict.
"""

self.__app.saved_config["scatterautorange_b"] = self._autorange.get()
self.__app.saved_config["scattercenter_s"] = self._centermode.get()
self.__app.saved_config["scatterscale_n"] = self._scale.get()
try:
self.__app.saved_config["scatterlat_f"] = float(self._reflat.get())
self.__app.saved_config["scatterlon_f"] = float(self._reflon.get())
except ValueError:
self.__app.saved_config["scatterlat_f"] = 0.0
self.__app.saved_config["scatterlon_f"] = 0.0

def _init_frame(self):
"""
Initialize scatter plot.
Expand Down Expand Up @@ -283,15 +307,16 @@ def _init_frame(self):
self.canvas.create_text(
txt_x, txt_y, text=dist, fill=FGCOL, font=self._lbl_font
)
for x, y, t in (
(width / 2, 5, "N"),
(width / 2, height - 5, "S"),
(5, height / 2, "W"),
(width - 5, height / 2, "E"),
):
self.canvas.create_text(
x, y, text=t, fill=FGCOL, font=self._lbl_font, anchor=t.lower()
)

for x, y, t in (
(width / 2, 5, "N"),
(width / 2, height - 5, "S"),
(5, height / 2, "W"),
(width - 5, height / 2, "E"),
):
self.canvas.create_text(
x, y, text=t, fill=FGCOL, font=self._lbl_font, anchor=t.lower()
)

def _draw_average(self, lbl_font: font):
"""
Expand Down Expand Up @@ -380,9 +405,9 @@ def _set_average(self):
ave_lat = sum(p.lat for p in self._points) / num
ave_lon = sum(p.lon for p in self._points) / num
self._average = Point(ave_lat, ave_lon)
if HASSTATS:
if HASSTATS and len(self._points) > 1:
self._stddev = Point(
pstdev(p.lat for p in self._points), pstdev(p.lon for p in self._points)
stdev(p.lat for p in self._points), stdev(p.lon for p in self._points)
)

def _set_bounds(self, center: Point):
Expand Down Expand Up @@ -452,15 +477,16 @@ def update_frame(self):
lon = float(lon)
except ValueError:
return # Invalid values for lat/lon get ignored.

if lat == 0.0 and lon == 0.0: # assume no fix
return
pos = Point(lat, lon)
if self.__app.gnss_status.fix == "NO FIX":
return # Don't plot when we don't have a fix.
if self._points and pos == self._points[-1]:
return # Don't repeat exactly the last point.

self._points.append(pos)
if len(self._points) > MAXPOINTS:
self._points.pop(0)
self._cull_points()

self._set_average()

Expand All @@ -479,6 +505,16 @@ def update_frame(self):

self._redraw()

def _cull_points(self):
"""
Limit number of points in in-memory array.
"""

if CULLMID: # cull from middle
self._points.pop(randrange(1, len(self._points) - 2))
else: # cull from start
self._points.pop(0)

def _do_autorange(self, middle: Point):
"""
Adjust range until all points in bounds.
Expand All @@ -489,10 +525,16 @@ def _do_autorange(self, middle: Point):
out = True
while out and self._scale.get() > 0:
out = False
for pt in self._points:
if not in_bounds(self._bounds, pt):

# include fixed reference point in autorange
if FIXINAUTO and not out and self._fixed is not None:
if not in_bounds(self._bounds, self._fixed):
out = True
break
if not out:
for pt in self._points:
if not in_bounds(self._bounds, pt):
out = True
break
if out:
self._scale.set(self._scale.get() - 1)
self._set_bounds(middle)
Expand Down
18 changes: 9 additions & 9 deletions src/pygpsclient/settings_frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -899,6 +899,15 @@ def config(self) -> dict:
0,
),
),
"scatterautorange_b": self.__app.saved_config.get(
"scatterautorange_b", 0
),
"scattercenter_s": self.__app.saved_config.get(
"scattercenter_s", "Average"
),
"scatterscale_n": self.__app.saved_config.get("scatterscale_n", 6),
"scatterlat_f": self.__app.saved_config.get("scatterlat_f", 0.0),
"scatterlon_f": self.__app.saved_config.get("scatterlon_f", 0.0),
# Manually edited config settings
"spartndecode_b": self.__app.saved_config.get("spartndecode_b", 0),
"spartnkey_s": self.__app.saved_config.get("spartnkey_s", ""),
Expand All @@ -910,15 +919,6 @@ def config(self) -> dict:
"colortags_l": self.__app.saved_config.get("colortags_l", []),
"ubxpresets_l": self.__app.saved_config.get("ubxpresets_l", []),
"usermaps_l": self.__app.saved_config.get("usermaps_l", []),
"scatterautorange_b": self.__app.saved_config.get(
"scatterautorange_b", 0
),
"scattercenter_s": self.__app.saved_config.get(
"scattercenter_s", "Average"
),
"scatterscale_n": self.__app.saved_config.get("scatterscale_n", 6),
"scatterlat_f": self.__app.saved_config.get("scatterlat_f", 0.0),
"scatterlon_f": self.__app.saved_config.get("scatterlon_f", 0.0),
}
return config
except (KeyError, ValueError, TypeError, TclError) as err:
Expand Down

0 comments on commit 95971c3

Please sign in to comment.