enode-host 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,49 @@
1
+ import wx
2
+
3
+ class ChoiceExample(wx.Frame):
4
+ def __init__(self, parent, title):
5
+ super(ChoiceExample, self).__init__(parent, title=title, size=(300, 200))
6
+
7
+ panel = wx.Panel(self)
8
+ sizer = wx.BoxSizer(wx.VERTICAL)
9
+
10
+ # Create a label
11
+ label = wx.StaticText(panel, label="Pick an option:")
12
+ sizer.Add(label, 0, wx.ALL | wx.CENTER, 10)
13
+
14
+ # Create a wx.Choice control with a list of strings
15
+ self.choice = wx.Choice(panel, choices=["Option 1", "Option 2", "Option 3"])
16
+ sizer.Add(self.choice, 0, wx.ALL | wx.CENTER, 5)
17
+
18
+ # Bind the choice selection event
19
+ self.choice.Bind(wx.EVT_CHOICE, self.on_choice)
20
+
21
+ # Create a label to display the selected item
22
+ self.display_label = wx.StaticText(panel, label="")
23
+ sizer.Add(self.display_label, 0, wx.ALL | wx.CENTER, 10)
24
+
25
+ panel.SetSizer(sizer)
26
+ self.Centre()
27
+ self.Show()
28
+
29
+ def on_choice(self, event):
30
+ """
31
+ Event handler for a selection from the wx.Choice control.
32
+ """
33
+ # Get the string corresponding to the selected item
34
+ selection = self.choice.GetString(self.choice.GetSelection())
35
+ print(self.choice.GetSelection())
36
+
37
+ # Update the display label
38
+ self.display_label.SetLabel(f"Selected: {selection}")
39
+
40
+
41
+ class MyApp(wx.App):
42
+ def OnInit(self):
43
+ frame = ChoiceExample(None, title="wx.Choice Example")
44
+ frame.Show()
45
+ return True
46
+
47
+ if __name__ == "__main__":
48
+ app = MyApp(False)
49
+ app.MainLoop()
@@ -0,0 +1,494 @@
1
+ #!/usr/local/bin/python3
2
+ # -*- coding: utf-8 -*-
3
+
4
+ #
5
+ # This is the file to construct GUI elements
6
+ #
7
+
8
+
9
+ ###########################################################################
10
+ ## Python code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
11
+ ## http://www.wxformbuilder.org/
12
+ ##
13
+ ## PLEASE DO *NOT* EDIT THIS FILE!
14
+ ###########################################################################
15
+
16
+ import wx
17
+ import wx.xrc
18
+ import wx.grid
19
+
20
+ import gettext
21
+ _ = gettext.gettext
22
+
23
+ import wx
24
+ import wx.lib.agw.aui as aui
25
+ import wx.lib.mixins.inspection as wit
26
+ from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
27
+ from matplotlib.backends.backend_wxagg import \
28
+ NavigationToolbar2WxAgg as NavigationToolbar
29
+ from matplotlib.figure import Figure
30
+ import wx.grid as gridlib
31
+ import queues
32
+ import datetime
33
+ from numpy import empty, where, array, delete, append, ones, nan, floor, shape
34
+ import random
35
+ import logging
36
+ import pandas as pd
37
+
38
+ logger = logging.getLogger(__name__)
39
+
40
+ class Plot(wx.Panel):
41
+ def __init__(self, parent, id=-1, dpi=None, **kwargs):
42
+ super().__init__(parent, id=id, **kwargs)
43
+ self.figure = Figure(dpi=dpi, figsize=(2, 2))
44
+ self.canvas = FigureCanvas(self, -1, self.figure)
45
+ self.toolbar = NavigationToolbar(self.canvas)
46
+ self.toolbar.Realize()
47
+
48
+ sizer = wx.BoxSizer(wx.VERTICAL)
49
+ sizer.Add(self.canvas, 1, wx.EXPAND)
50
+ sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND)
51
+ self.SetSizer(sizer)
52
+
53
+ class PandasTable(wx.grid.GridTableBase):
54
+ def __init__(self, dataframe):
55
+ wx.grid.GridTableBase.__init__(self)
56
+ self.dataframe = dataframe
57
+
58
+ def GetNumberRows(self):
59
+ return self.dataframe.shape[0]
60
+
61
+ def GetNumberCols(self):
62
+ return self.dataframe.shape[1]
63
+
64
+ def GetValue(self, row, col):
65
+ # Fetch value from pandas DataFrame
66
+ return str(self.dataframe.iat[row, col])
67
+
68
+ def SetValue(self, row, col, value):
69
+ # Set value in pandas DataFrame
70
+ self.dataframe.iat[row, col] = value
71
+ self.GetView().ForceRefresh()
72
+
73
+ def GetColLabelValue(self, col):
74
+ # Get column names from pandas DataFrame
75
+ return str(self.dataframe.columns[col])
76
+
77
+ def GetRowLabelValue(self, row):
78
+ # Optional: Get row indices from pandas DataFrame
79
+ return str(self.dataframe.index[row])
80
+
81
+ def update_table(self):
82
+ # msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_NOTIFY_TABLE_RESET)
83
+ msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_NOTIFY_ROWS_APPENDED)
84
+ self.GetView().ProcessTableMessage(msg)
85
+
86
+
87
+ ###########################################################################
88
+ ## Class View
89
+ ###########################################################################
90
+
91
+ class View(wx.Frame):
92
+
93
+ def __init__(self, parent):
94
+
95
+ wx.Frame.__init__ ( self, None, id = wx.ID_ANY, title = _(u"Wireless Sensor DAQ"), pos = wx.DefaultPosition, size = wx.Size( 1024,600 ), style = wx.DEFAULT_FRAME_STYLE|wx.TAB_TRAVERSAL )
96
+
97
+ self.controller = parent
98
+ self.model = self.controller.model
99
+ self.m_table = None
100
+ self.timehistory_lines = {}
101
+ self.psd_lines = {}
102
+ self.PPS_outdate_check = True
103
+ self.channel_selection = [False, True, False]
104
+ self.timespan_length = 30 # seconds
105
+
106
+ self.SetSizeHints( wx.DefaultSize, wx.DefaultSize )
107
+
108
+ bSizer1 = wx.BoxSizer( wx.VERTICAL )
109
+ bSizer2 = wx.BoxSizer( wx.HORIZONTAL )
110
+
111
+ self.m_staticText2 = wx.StaticText( self, wx.ID_ANY, _(u"Sensor Nodes:"), wx.DefaultPosition, wx.DefaultSize, 0 )
112
+ self.m_staticText2.Wrap(-1)
113
+ bSizer2.Add( self.m_staticText2, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5 )
114
+
115
+ self.m_textCtrl2 = wx.TextCtrl( self, wx.ID_ANY, self.controller.model.options['node_nums_txt'], wx.DefaultPosition, wx.DefaultSize, 0)
116
+ bSizer2.Add( self.m_textCtrl2, 1, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5 )
117
+
118
+ # # Fs selection
119
+ # self.m_staticText3 = wx.StaticText( self, wx.ID_ANY, _(u"Fs="), wx.DefaultPosition, wx.DefaultSize, 0 )
120
+ # self.m_staticText3.Wrap(-1)
121
+ # bSizer2.Add( self.m_staticText3, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5 )
122
+
123
+ # m_choice1Choices = [ _(u"62.5"), _(u"125") ]
124
+ # self.m_choice1 = wx.Choice( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, m_choice1Choices, 0 )
125
+ # self.m_choice1.SetSelection( 0 )
126
+ # bSizer2.Add( self.m_choice1, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5 )
127
+
128
+ # self.m_staticText4 = wx.StaticText( self, wx.ID_ANY, _(u"Hz"), wx.DefaultPosition, wx.DefaultSize, 0 )
129
+ # self.m_staticText4.Wrap(-1)
130
+ # bSizer2.Add( self.m_staticText4, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5 )
131
+
132
+ # Operation Mode Choice
133
+
134
+ self.m_staticText4 = wx.StaticText( self, wx.ID_ANY, _(u"Operation Mode :"), wx.DefaultPosition, wx.DefaultSize, 0 )
135
+ self.m_staticText4.Wrap(-1)
136
+ bSizer2.Add( self.m_staticText4, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5 )
137
+
138
+ self.m_choice_OperationMode = wx.Choice(self, choices=["Online DAQ", "Standalone - Data Peeking", "Post-DAQ Data Stream", "Maintenance"])
139
+ bSizer2.Add(self.m_choice_OperationMode, 0, wx.ALL | wx.CENTER, 5)
140
+ self.m_choice_OperationMode.SetStringSelection("Online DAQ")
141
+
142
+ # Start Button
143
+ self.m_button1 = wx.Button( self, wx.ID_ANY, _(u"Start"), wx.DefaultPosition, wx.DefaultSize, 0 )
144
+ bSizer2.Add(self.m_button1, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5 )
145
+
146
+ # Stop Button
147
+ self.m_button2 = wx.Button( self, wx.ID_ANY, _(u"Stop"), wx.DefaultPosition, wx.DefaultSize, 0 )
148
+ bSizer2.Add(self.m_button2, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5 )
149
+
150
+
151
+ bSizer1.Add(bSizer2, 0, wx.EXPAND, 5 )
152
+
153
+ bSizer3 = wx.BoxSizer( wx.HORIZONTAL )
154
+ bSizer4 = wx.BoxSizer( wx.VERTICAL )
155
+
156
+ self.m_staticText21 = wx.StaticText( self, wx.ID_ANY, _(u"WiFi Mesh Status"), wx.DefaultPosition, wx.DefaultSize, 0 )
157
+ self.m_staticText21.Wrap(-1)
158
+
159
+ bSizer4.Add( self.m_staticText21, 0, wx.ALL, 5 )
160
+
161
+ self.m_grid2 = wx.grid.Grid( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, 0 )
162
+ self.mesh_status_data_view()
163
+
164
+ # Grid
165
+ self.nrows = len(self.controller.model.node_nums)
166
+ # self.m_grid2.CreateGrid(self.nrows, 6)
167
+ # self.m_grid2.EnableEditing( True )
168
+ # self.m_grid2.EnableGridLines( True )
169
+ # self.m_grid2.EnableDragGridSize( True )
170
+ # self.m_grid2.SetMargins( 0, 0 )
171
+
172
+ # self.m_grid2.SetColSize( 3, 40 )
173
+ # self.m_grid2.SetColSize( 4, 40 )
174
+ # self.m_grid2.SetColSize( 5, 45 )
175
+ # self.m_grid2.EnableDragColMove( False )
176
+ # self.m_grid2.EnableDragColSize( True )
177
+ # self.m_grid2.SetColLabelValue( 0, _(u"Node ID") )
178
+ # self.m_grid2.SetColLabelValue( 1, _(u"Status") )
179
+ # self.m_grid2.SetColLabelValue( 2, _(u"L") )
180
+ # self.m_grid2.SetColLabelValue( 3, _(u"RSSI") )
181
+ # self.m_grid2.SetColLabelValue( 4, _(u"PPS") )
182
+ # self.m_grid2.SetColLabelValue( 5, _(u"Data") )
183
+ # self.m_grid2.SetColLabelSize( wx.grid.GRID_AUTOSIZE )
184
+ # self.m_grid2.SetColLabelAlignment( wx.ALIGN_CENTER, wx.ALIGN_CENTER )
185
+
186
+ # # Rows
187
+ # self.m_grid2.EnableDragRowSize( True )
188
+ self.m_grid2.SetRowLabelSize( wx.grid.GRID_AUTOSIZE )
189
+ # self.m_grid2.SetRowLabelAlignment( wx.ALIGN_CENTER, wx.ALIGN_CENTER )
190
+
191
+ # # Label Appearance
192
+
193
+ # # Cell Defaults
194
+ self.m_grid2.SetDefaultCellAlignment( wx.ALIGN_CENTER, wx.ALIGN_CENTER)
195
+ # self.m_grid2.AutoSizeColumns()
196
+ bSizer4.Add( self.m_grid2, 1, wx.ALL|wx.EXPAND, 5 )
197
+
198
+ bSizer3.Add( bSizer4, 0, wx.EXPAND, 5 )
199
+
200
+ self.m_notebook2 = wx.Notebook( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, 0 )
201
+ self.m_panel1 = wx.Panel( self.m_notebook2, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
202
+ self.m_notebook2.AddPage( self.m_panel1, _(u"Time history plot"), True )
203
+ self.m_panel2 = wx.Panel( self.m_notebook2, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
204
+ self.m_notebook2.AddPage( self.m_panel2, _(u"PSD plot"), False )
205
+
206
+ bSizer3.Add( self.m_notebook2, 1, wx.ALL|wx.EXPAND, 5 )
207
+
208
+ bSizer1.Add( bSizer3, 1, wx.EXPAND, 5 )
209
+
210
+ self.m_textCtrl21 = wx.TextCtrl( self, wx.ID_ANY, _(u"status reporting panel"), wx.DefaultPosition, wx.Size( -1,100 ), wx.TE_MULTILINE )
211
+ bSizer1.Add( self.m_textCtrl21, 0, wx.ALL|wx.EXPAND, 5 )
212
+
213
+
214
+ self.SetSizer( bSizer1 )
215
+ self.Layout()
216
+
217
+
218
+ # MENU
219
+ self.m_statusBar1 = self.CreateStatusBar(1, wx.STB_SIZEGRIP, wx.ID_ANY)
220
+ self.m_menubar = wx.MenuBar(0)
221
+ self.m_menu_file = wx.Menu()
222
+ self.m_menu_file_open = wx.MenuItem(self.m_menu_file, wx.ID_ANY, _(u"&Open"), wx.EmptyString, wx.ITEM_NORMAL)
223
+ self.m_menu_file_save = wx.MenuItem(self.m_menu_file, wx.ID_ANY, _(u"&Save"), wx.EmptyString, wx.ITEM_NORMAL)
224
+ self.m_menu_file_quit = wx.MenuItem(self.m_menu_file, wx.ID_ANY, _(u"&Quit"), wx.EmptyString, wx.ITEM_NORMAL)
225
+ self.m_menu_file.Append(self.m_menu_file_open)
226
+ self.m_menu_file.Append(self.m_menu_file_save)
227
+ self.m_menu_file.AppendSeparator()
228
+ self.m_menu_file.Append(self.m_menu_file_quit)
229
+ self.m_menubar.Append(self.m_menu_file, _(u"&File"))
230
+
231
+ self.m_menu_data = wx.Menu()
232
+ self.m_menu_data_export = wx.MenuItem(self.m_menu_file, wx.ID_ANY, _(u"&Export"), wx.EmptyString, wx.ITEM_NORMAL)
233
+ self.m_menu_data.Append(self.m_menu_data_export)
234
+ self.m_menubar.Append(self.m_menu_data, _(u"&Data"))
235
+
236
+ self.m_menu_cmd = wx.Menu()
237
+ self.m_menu_cmd_sdclear = wx.MenuItem(self.m_menu_cmd, wx.ID_ANY, _(u"SD &Clear"), wx.EmptyString, wx.ITEM_NORMAL)
238
+ self.m_menu_cmd.Append(self.m_menu_cmd_sdclear)
239
+ self.m_menu_cmd_shutdown = wx.MenuItem(self.m_menu_cmd, wx.ID_ANY, _(u"&Shutdown"), wx.EmptyString, wx.ITEM_NORMAL)
240
+ self.m_menu_cmd.Append(self.m_menu_cmd_shutdown)
241
+ self.m_menubar.Append(self.m_menu_cmd, _(u"&CMD"))
242
+
243
+
244
+ self.m_menu_view = wx.Menu()
245
+ self.m_menu_view_clf = wx.MenuItem(self.m_menu_view, wx.ID_ANY, _(u"&Clear Figure"), wx.EmptyString, wx.ITEM_NORMAL)
246
+ self.m_menu_view.Append(self.m_menu_view_clf)
247
+
248
+ self.m_menu_view_chsel = wx.Menu()
249
+ self.m_menu_view_chsel_x = self.m_menu_view_chsel.AppendCheckItem(wx.ID_ANY, "X")
250
+ self.m_menu_view_chsel_y = self.m_menu_view_chsel.AppendCheckItem(wx.ID_ANY, "Y")
251
+ self.m_menu_view_chsel_z = self.m_menu_view_chsel.AppendCheckItem(wx.ID_ANY, "Z")
252
+ self.m_menu_view_chsel_y.Check(True)
253
+ self.m_menu_view.AppendSubMenu(self.m_menu_view_chsel, "Channel Selection")
254
+ self.Bind(wx.EVT_MENU, self.onChannelToggled, self.m_menu_view_chsel_x)
255
+ self.Bind(wx.EVT_MENU, self.onChannelToggled, self.m_menu_view_chsel_y)
256
+ self.Bind(wx.EVT_MENU, self.onChannelToggled, self.m_menu_view_chsel_z)
257
+
258
+
259
+ self.m_menu_view_timespan = wx.Menu()
260
+ self.m_menu_view_timespan_radio_30s = self.m_menu_view_timespan.AppendRadioItem(wx.ID_ANY, "30 sec")
261
+ self.m_menu_view_timespan_radio_20s = self.m_menu_view_timespan.AppendRadioItem(wx.ID_ANY, "20 sec")
262
+ self.m_menu_view_timespan_radio_10s = self.m_menu_view_timespan.AppendRadioItem(wx.ID_ANY, "10 sec")
263
+ self.m_menu_view_timespan_radio_05s = self.m_menu_view_timespan.AppendRadioItem(wx.ID_ANY, "5 sec")
264
+ self.m_menu_view_timespan_radio_02s = self.m_menu_view_timespan.AppendRadioItem(wx.ID_ANY, "2 sec")
265
+ self.m_menu_view_timespan_radio_30s.Check(True)
266
+ self.m_menu_view.AppendSubMenu(self.m_menu_view_timespan, "Timespan Select")
267
+ self.Bind(wx.EVT_MENU, self.onTimeSpanChange, self.m_menu_view_timespan_radio_30s)
268
+ self.Bind(wx.EVT_MENU, self.onTimeSpanChange, self.m_menu_view_timespan_radio_20s)
269
+ self.Bind(wx.EVT_MENU, self.onTimeSpanChange, self.m_menu_view_timespan_radio_10s)
270
+ self.Bind(wx.EVT_MENU, self.onTimeSpanChange, self.m_menu_view_timespan_radio_05s)
271
+ self.Bind(wx.EVT_MENU, self.onTimeSpanChange, self.m_menu_view_timespan_radio_02s)
272
+
273
+
274
+ self.m_menubar.Append(self.m_menu_view, _(u"&View"))
275
+
276
+ self.m_menu_help = wx.Menu()
277
+ self.m_menu_help_about = wx.MenuItem(self.m_menu_help, wx.ID_ANY, _(u"&Help"), wx.EmptyString, wx.ITEM_NORMAL)
278
+ self.m_menu_help.Append(self.m_menu_help_about)
279
+ self.m_menubar.Append(self.m_menu_help, _(u"&Help"))
280
+
281
+ self.SetMenuBar(self.m_menubar)
282
+ self.Centre( wx.BOTH )
283
+
284
+ # FIGURE PANEL
285
+
286
+ self.m_fig1 = Plot(self.m_panel1)
287
+ self.axes1 = self.m_fig1.figure.add_subplot()
288
+ self.m_fig2 = Plot(self.m_panel2)
289
+ self.axes2 = self.m_fig2.figure.add_subplot()
290
+ self.init_plot()
291
+
292
+ canvas1 = FigureCanvas(self.m_panel1, -1, self.m_fig1.figure)
293
+ sizer1 = wx.BoxSizer(wx.VERTICAL)
294
+ sizer1.Add(canvas1, 1, wx.EXPAND)
295
+
296
+ canvas2 = FigureCanvas(self.m_panel2, -1, self.m_fig2.figure)
297
+ sizer2 = wx.BoxSizer(wx.VERTICAL)
298
+ sizer2.Add(canvas2, 1, wx.EXPAND)
299
+
300
+ # Set the sizer for the panel1
301
+ self.m_panel1.SetSizer(sizer1)
302
+ self.m_panel2.SetSizer(sizer2)
303
+
304
+ # UPDATE TIMER
305
+
306
+ self.timer = wx.Timer(self)
307
+ self.Bind(wx.EVT_TIMER, self.gui_update, self.timer)
308
+ self.timer.Start(1000)
309
+
310
+
311
+ self.timespan_map = {
312
+ self.m_menu_view_timespan_radio_30s.GetId(): 30,
313
+ self.m_menu_view_timespan_radio_20s.GetId(): 20,
314
+ self.m_menu_view_timespan_radio_10s.GetId(): 10,
315
+ self.m_menu_view_timespan_radio_05s.GetId(): 5,
316
+ self.m_menu_view_timespan_radio_02s.GetId(): 2,
317
+ }
318
+
319
+ def mesh_status_data_view(self):
320
+
321
+ self.m_table = PandasTable(self.controller.model.mesh_status_data)
322
+ self.m_grid2.SetTable(self.m_table, takeOwnership=True)
323
+ # Columns
324
+ self.m_grid2.SetColSize( 0, 70 ) # Node ID
325
+ self.m_grid2.SetColSize( 1, 100 ) # Status
326
+ self.m_grid2.SetColSize( 2, 20 ) # L
327
+ self.m_grid2.SetColSize( 3, 70 ) # Parent
328
+ self.m_grid2.SetColSize( 4, 40 ) # RSSI
329
+ self.m_grid2.SetColSize( 5, 70 ) # Children
330
+ self.m_grid2.SetColSize( 6, 40 ) # PPS
331
+ self.m_grid2.SetColSize( 7, 50 ) # CMD
332
+ self.m_grid2.SetColSize( 8, 0 ) # PPS-time
333
+ self.m_grid2.SetColSize( 9, 0 ) # Parent's MAC
334
+ self.m_grid2.SetColSize(10, 0 ) # Self MAC
335
+ self.m_grid2.SetColSize(11, 0 ) # Conn Report Time
336
+ self.m_grid2.SetColSize(12, 0 ) # inode
337
+
338
+ def __del__( self ):
339
+ pass
340
+
341
+ # Virtual event handlers, override them in your derived class
342
+ def test( self, event ):
343
+ event.Skip()
344
+
345
+ # def init_plot(self, parent, id=-1, dpi=None, **kwargs):
346
+ # wx.Panel.__init__(parent)
347
+ # self.figure = Figure(dpi=dpi, figsize=(2, 2))
348
+ # self.canvas = FigureCanvas(self, -1, self.figure)
349
+ # self.toolbar = NavigationToolbar(self.canvas)
350
+ # self.toolbar.Realize()
351
+
352
+ # sizer = wx.BoxSizer(wx.VERTICAL)
353
+ # sizer.Add(self.canvas, 1, wx.EXPAND)
354
+ # sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND)
355
+ # self.SetSizer(sizer)
356
+
357
+ # return self.figure
358
+
359
+ def getTimeWindow(self, t1):
360
+ Tspan = self.timespan_length
361
+ r = [datetime.datetime.fromtimestamp(floor(t1.timestamp() / Tspan) * Tspan),
362
+ datetime.datetime.fromtimestamp(floor(t1.timestamp() / Tspan + 1) * Tspan)]
363
+ # logger.info("{}, {}".format(r[0], r[1]))
364
+ return r
365
+
366
+ def init_plot(self):
367
+
368
+ self.axes1.cla()
369
+ for index, row in self.model.mesh_status_data.iterrows():
370
+ for idx, ch in enumerate(['X', 'Y', 'Z']):
371
+ if self.channel_selection[idx]:
372
+ NodeID_CH = row['Node ID'] + ch
373
+ self.timehistory_lines[NodeID_CH] = self.axes1.plot([], [], label=NodeID_CH)[0]
374
+ self.axes1.set_xlabel('Time')
375
+ self.axes1.set_ylabel('Acceleration (g)')
376
+ self.axes1.grid(True)
377
+ self.axes1.set_ylim(-2, 2)
378
+ self.axes1.legend()
379
+
380
+ self.axes2.cla()
381
+ for index, row in self.model.mesh_status_data.iterrows():
382
+ for idx, ch in enumerate(['X', 'Y', 'Z']):
383
+ if self.channel_selection[idx]:
384
+ NodeID_CH = row['Node ID'] + ch
385
+ self.psd_lines[NodeID_CH] = self.axes2.semilogy([], [], label=NodeID_CH)[0]
386
+
387
+ self.axes2.set_xlabel('Frequency (Hz)')
388
+ self.axes2.set_ylabel('ASD (g/sq(Hz))')
389
+ self.axes2.grid(True)
390
+ self.axes2.set_ylim(1e-6, 1e1)
391
+ self.axes2.set_xlim(0, 25)
392
+ self.axes2.legend()
393
+
394
+ def status_table_update(self):
395
+
396
+ t_now = datetime.datetime.now()
397
+ for index, row in self.model.mesh_status_data.iterrows():
398
+ if row['Connection'] == 'disconnected':
399
+ attr = gridlib.GridCellAttr()
400
+ attr.SetBackgroundColour(wx.Colour(255, 0, 0)) # light Red
401
+ self.m_grid2.SetAttr(index, 1, attr)
402
+ else:
403
+ attr = gridlib.GridCellAttr()
404
+ attr.SetBackgroundColour(wx.Colour(255, 255, 255)) # light Red
405
+ self.m_grid2.SetAttr(index, 1, attr)
406
+
407
+ if isinstance(row['PPS-time'], datetime.datetime) and self.PPS_outdate_check:
408
+ dt = t_now - row['PPS-time']
409
+ if dt.seconds > 10:
410
+ attr = gridlib.GridCellAttr()
411
+ attr.SetBackgroundColour(wx.Colour(255, 0, 0)) # light Red
412
+ self.m_grid2.SetAttr(index, 6, attr)
413
+ else:
414
+ attr = gridlib.GridCellAttr()
415
+ attr.SetBackgroundColour(wx.Colour(255, 255, 255)) # light Red
416
+ self.m_grid2.SetAttr(index, 6, attr)
417
+
418
+ if row['Connection'] == 'connected' and not isinstance(row['PPS-time'], datetime.datetime):
419
+ attr = gridlib.GridCellAttr()
420
+ attr.SetBackgroundColour(wx.Colour(255, 0, 0)) # light Red
421
+ self.m_grid2.SetAttr(index, 6, attr)
422
+
423
+ def table_update(self):
424
+
425
+ self.m_grid2.ForceRefresh()
426
+ self.status_table_update()
427
+
428
+ def figure_update(self):
429
+
430
+ for index, row in self.model.mesh_status_data.iterrows():
431
+ nodeID = row['nodeID']
432
+ for idx, ch in enumerate(['X', 'Y', 'Z']):
433
+ NodeID_CH = row['Node ID'] + ch
434
+ if NodeID_CH in self.timehistory_lines.keys() and nodeID in self.model.timehistory_xdata.keys():
435
+ with self.model.plot_mutex[nodeID]:
436
+ if len(self.model.timehistory_xdata[nodeID]) > 1:
437
+ self.timehistory_lines[NodeID_CH].set_xdata(self.model.timehistory_xdata[nodeID])
438
+ self.timehistory_lines[NodeID_CH].set_ydata(self.model.timehistory_ydata[nodeID][:, idx])
439
+ if self.model.timehistory_xlim:
440
+ self.axes1.set_xlim(self.model.timehistory_xlim)
441
+ try:
442
+ # for nodeID in self.timehistory_lines:
443
+ # logger.info('draw(): {} / {} / {}'.format(nodeID, shape(self.timehistory_lines[nodeID].get_xdata()), shape(self.timehistory_lines[nodeID].get_ydata())))
444
+ self.m_fig1.figure.canvas.draw()
445
+ # for nodeID in self.timehistory_lines:
446
+ # logger.info('draw(): {} / {} / {}'.format(nodeID, shape(self.timehistory_lines[nodeID].get_xdata()), shape(self.timehistory_lines[nodeID].get_ydata())))
447
+ except:
448
+ # pass
449
+ raise
450
+
451
+ for index, row in self.model.mesh_status_data.iterrows():
452
+ nodeID = row['nodeID']
453
+ for idx, ch in enumerate(['X', 'Y', 'Z']):
454
+ NodeID_CH = row['Node ID'] + ch
455
+ if NodeID_CH in self.psd_lines.keys() and nodeID in self.model.psd_ydata.keys():
456
+ with self.model.plot_mutex[nodeID]:
457
+ self.psd_lines[NodeID_CH].set_xdata(self.model.psd_xdata)
458
+ self.psd_lines[NodeID_CH].set_ydata(self.model.psd_ydata[nodeID][:, idx])
459
+
460
+ if len(self.model.psd_xdata) > 0:
461
+ self.axes2.set_xlim(0, round(self.model.psd_xdata[-1]))
462
+ try:
463
+ self.m_fig2.figure.canvas.draw()
464
+ except:
465
+ # pass
466
+ raise
467
+
468
+ # self.m_fig2.figure.canvas.draw()
469
+
470
+ def gui_update(self, event):
471
+
472
+ self.table_update()
473
+ self.figure_update()
474
+
475
+
476
+ def onChannelToggled(self, event):
477
+
478
+ self.channel_selection = [
479
+ self.m_menu_view_chsel_x.IsChecked(),
480
+ self.m_menu_view_chsel_y.IsChecked(),
481
+ self.m_menu_view_chsel_z.IsChecked()
482
+ ]
483
+
484
+ self.init_plot()
485
+
486
+ def onTimeSpanChange(self, event):
487
+
488
+ ts = self.timespan_map.get(event.GetId(), None)
489
+ if ts:
490
+ logger.info(f"Timespan selected: {ts} sec")
491
+ self.timespan_length = ts
492
+
493
+
494
+
@@ -0,0 +1,55 @@
1
+ import wx
2
+ import wx.lib.agw.aui as aui
3
+ import wx.lib.mixins.inspection as wit
4
+
5
+ from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
6
+ from matplotlib.backends.backend_wxagg import \
7
+ NavigationToolbar2WxAgg as NavigationToolbar
8
+ from matplotlib.figure import Figure
9
+
10
+
11
+ class Plot(wx.Panel):
12
+ def __init__(self, parent, id=-1, dpi=None, **kwargs):
13
+ super().__init__(parent, id=id, **kwargs)
14
+ self.figure = Figure(dpi=dpi, figsize=(2, 2))
15
+ self.canvas = FigureCanvas(self, -1, self.figure)
16
+ self.toolbar = NavigationToolbar(self.canvas)
17
+ self.toolbar.Realize()
18
+
19
+ sizer = wx.BoxSizer(wx.VERTICAL)
20
+ sizer.Add(self.canvas, 1, wx.EXPAND)
21
+ sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND)
22
+ self.SetSizer(sizer)
23
+
24
+
25
+ class PlotNotebook(wx.Panel):
26
+ def __init__(self, parent, id=-1):
27
+ super().__init__(parent, id=id)
28
+ self.nb = aui.AuiNotebook(self)
29
+ sizer = wx.BoxSizer()
30
+ sizer.Add(self.nb, 1, wx.EXPAND)
31
+ self.SetSizer(sizer)
32
+
33
+ def add(self, name="plot"):
34
+ page = Plot(self.nb)
35
+ self.nb.AddPage(page, name)
36
+ return page.figure
37
+
38
+
39
+ def demo():
40
+ # Alternatively you could use:
41
+ # app = wx.App()
42
+ # InspectableApp is a great debug tool, see:
43
+ # http://wiki.wxpython.org/Widget%20Inspection%20Tool
44
+ app = wit.InspectableApp()
45
+ frame = wx.Frame(None, -1, 'Plotter')
46
+ plotter = PlotNotebook(frame)
47
+ axes1 = plotter.add('figure 1').add_subplot()
48
+ axes1.plot([1, 2, 3], [2, 1, 4])
49
+ axes2 = plotter.add('figure 2').add_subplot()
50
+ axes2.plot([1, 2, 3, 4, 5], [2, 1, 4, 2, 3])
51
+ frame.Show()
52
+ app.MainLoop()
53
+
54
+ if __name__ == "__main__":
55
+ demo()
@@ -0,0 +1,43 @@
1
+ import wx
2
+
3
+ class MyFrame(wx.Frame):
4
+ def __init__(self):
5
+ super().__init__(None, title="Menu with Tick Marks", size=(300, 200))
6
+
7
+ menuBar = wx.MenuBar()
8
+ modeMenu = wx.Menu()
9
+
10
+ self.mode_auto = modeMenu.AppendRadioItem(wx.ID_ANY, "Auto")
11
+ self.mode_manual = modeMenu.AppendRadioItem(wx.ID_ANY, "Manual")
12
+ self.mode_custom = modeMenu.AppendRadioItem(wx.ID_ANY, "Custom")
13
+
14
+ menuBar.Append(modeMenu, "&Mode")
15
+ self.SetMenuBar(menuBar)
16
+
17
+ # Set default ticked item
18
+ self.mode_auto.Check(True)
19
+
20
+ # Bind events
21
+ self.Bind(wx.EVT_MENU, self.on_select_mode, self.mode_auto)
22
+ self.Bind(wx.EVT_MENU, self.on_select_mode, self.mode_manual)
23
+ self.Bind(wx.EVT_MENU, self.on_select_mode, self.mode_custom)
24
+
25
+ def on_select_mode(self, event):
26
+ selected = "?"
27
+ if self.mode_auto.IsChecked():
28
+ selected = "Auto"
29
+ elif self.mode_manual.IsChecked():
30
+ selected = "Manual"
31
+ elif self.mode_custom.IsChecked():
32
+ selected = "Custom"
33
+
34
+ wx.MessageBox(f"You selected: {selected}")
35
+
36
+ class MyApp(wx.App):
37
+ def OnInit(self):
38
+ frame = MyFrame()
39
+ frame.Show()
40
+ return True
41
+
42
+ app = MyApp(False)
43
+ app.MainLoop()