IDE: Fixed variable traces graphs RingBuffers. Removed an apparently useless wxCallAfter in trend graph that was leading to pydeadobject exception on wxGTK when double-clicking. svghmi
authorEdouard Tisserant
Wed, 16 Jun 2021 12:15:02 +0200
branchsvghmi
changeset 3258 5ce56021f166
parent 3257 095c73591b7e
child 3260 6bd918732047
IDE: Fixed variable traces graphs RingBuffers. Removed an apparently useless wxCallAfter in trend graph that was leading to pydeadobject exception on wxGTK when double-clicking.
controls/DebugVariablePanel/DebugVariableItem.py
controls/DebugVariablePanel/DebugVariablePanel.py
controls/DebugVariablePanel/DebugVariableTextViewer.py
controls/DebugVariablePanel/RingBuffer.py
--- a/controls/DebugVariablePanel/DebugVariableItem.py	Mon Jun 14 16:48:39 2021 +0200
+++ b/controls/DebugVariablePanel/DebugVariableItem.py	Wed Jun 16 12:15:02 2021 +0200
@@ -384,7 +384,7 @@
         ticks = self.Data.view[:, 0]
 
         # Get nearest data from tick
-        idx = np.searchsorted(ticks, tick)
+        idx = min(np.searchsorted(ticks, tick), self.Data.count - 1)
 
         # Adjust data index according to constraint
         if adjust < 0 and ticks[idx] > tick and idx > 0 or \
--- a/controls/DebugVariablePanel/DebugVariablePanel.py	Mon Jun 14 16:48:39 2021 +0200
+++ b/controls/DebugVariablePanel/DebugVariablePanel.py	Wed Jun 16 12:15:02 2021 +0200
@@ -357,9 +357,13 @@
 
             # Force refresh if graph is fixed because range of data received
             # is too small to fill data range selected
-            if self.Fixed and \
-               self.Ticks.view[-1] - self.Ticks.view[0] < self.CurrentRange:
-                self.Force = True
+            if self.Fixed :
+                if self.Ticks.view[-1] - self.Ticks.view[0] < self.CurrentRange:
+                    self.Force = True
+                if self.Ticks.view[0] > self.StartTick:
+                    self.StartTick = self.Ticks.view[0]
+                    self.Force = True
+
 
             self.HasNewData = False
             self.RefreshView()
@@ -388,14 +392,14 @@
         if self.CursorTick is not None:
             cursor_tick = max(self.Ticks.view[0],
                               min(self.CursorTick + move, self.Ticks.view[-1]))
-            cursor_tick_idx = np.searchsorted(self.Ticks.view, cursor_tick)
+            cursor_tick_idx = min(np.searchsorted(self.Ticks.view, cursor_tick), self.Ticks.count - 1)
             if self.Ticks.view[cursor_tick_idx] == self.CursorTick:
                 cursor_tick_idx = max(0,
                                       min(cursor_tick_idx + abs(move) // move,
                                           self.Ticks.count - 1))
             self.CursorTick = self.Ticks.view[cursor_tick_idx]
             self.StartTick = max(
-                self.Ticks.view[np.searchsorted(self.Ticks.view,  self.CursorTick + self.CurrentRange)],
+                self.Ticks.view[min(np.searchsorted(self.Ticks.view,  self.CursorTick - self.CurrentRange), self.Ticks.count - 1)],
                 min(self.StartTick, self.CursorTick))
             self.RefreshCanvasPosition()
             self.UpdateCursorTick()
@@ -605,7 +609,7 @@
 
     def SetCanvasPosition(self, tick):
         tick = max(self.Ticks.view[0], min(tick, self.Ticks.view[-1] - self.CurrentRange))
-        self.StartTick = self.Ticks.view[np.searchsorted(self.Ticks.view, tick)]
+        self.StartTick = self.Ticks.view[min(np.searchsorted(self.Ticks.view, tick), self.Ticks.count - 1)]
         self.Fixed = True
         self.RefreshCanvasPosition()
         self.ForceRefresh()
@@ -631,7 +635,7 @@
                     tick = self.StartTick + self.CurrentRange / 2.
                 new_start_tick = min(tick - (tick - self.StartTick) * self.CurrentRange / current_range,
                                      self.Ticks.view[-1] - self.CurrentRange)
-                self.StartTick = self.Ticks.view[np.searchsorted(self.Ticks.view, - new_start_tick)]
+                self.StartTick = self.Ticks.view[min(np.searchsorted(self.Ticks.view, new_start_tick), self.Ticks.count - 1)]
                 self.Fixed = new_start_tick < self.Ticks.view[-1] - self.CurrentRange
             self.ForceRefresh()
 
--- a/controls/DebugVariablePanel/DebugVariableTextViewer.py	Mon Jun 14 16:48:39 2021 +0200
+++ b/controls/DebugVariablePanel/DebugVariableTextViewer.py	Wed Jun 16 12:15:02 2021 +0200
@@ -270,7 +270,7 @@
         """
         # Execute callback on button under mouse pointer if it exists
         x, y = event.GetPosition()
-        wx.CallAfter(self.HandleButton, x, y)
+        self.HandleButton(x, y)
         event.Skip()
 
     def OnLeftDClick(self, event):
--- a/controls/DebugVariablePanel/RingBuffer.py	Mon Jun 14 16:48:39 2021 +0200
+++ b/controls/DebugVariablePanel/RingBuffer.py	Wed Jun 16 12:15:02 2021 +0200
@@ -12,36 +12,32 @@
 
 
 class RingBuffer(object):
-    def __init__(self, width=None, size=65536, padding=None):
+    def __init__(self, width=None, size=131072, padding=None):
         self.size = size
         self.padding = size if padding is None else padding
         shape = (self.size+self.padding,)
         if width :
             shape += (width,)
         self.buffer = np.zeros(shape)
-        self.counter = 0
-        self.full = False
+        self.cursor = 0
 
     def append(self, data):
         """this is an O(n) operation"""
-        data = data[-self.padding:]
+        data = data[-self.size:]
         n = len(data)
-        if self.remaining < n: self.compact()
-        self.buffer[self.counter+self.size:][:n] = data
-        self.counter += n
+        if self.size + self.padding - self.cursor < n:
+            self.compact()
+        self.buffer[self.cursor:][:n] = data
+        self.cursor += n
 
     @property
     def count(self):
-        return self.counter if not self.full else self.size
-
-    @property
-    def remaining(self):
-        return self.padding-self.counter
+        return min(self.size, self.cursor)
 
     @property
     def view(self):
         """this is always an O(1) operation"""
-        return self.buffer[self.counter:][:self.size]
+        return self.buffer[max(0, self.cursor - self.size):][:self.count]
 
     def compact(self):
         """
@@ -49,7 +45,6 @@
         and this cost is amortized over the whole padding space
         """
         print 'compacting'
-        self.buffer[:self.size] = self.view
-        self.counter = 0
-        self.full = True
+        self.buffer[:self.count] = self.view
+        self.cursor -= self.size