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,93 @@
1
+ # %%
2
+ import pandas as pd
3
+ import matplotlib.pyplot as plt
4
+ import matplotlib.dates as mdates
5
+
6
+ import pandas as pd
7
+
8
+ df = pd.read_hdf("data/daq-2025_0305_1719", key="df")
9
+
10
+ def select_xrange(self):
11
+ """
12
+ Plots the current DataFrame (with datetime index),
13
+ shows a vertical line following mouse movement (when zoom tool is NOT active),
14
+ and captures two mouse clicks (when zoom tool is NOT active).
15
+ Returns the subset of the DataFrame between those two clicked x-coordinates.
16
+ """
17
+ # Create the plot
18
+ fig, ax = plt.subplots()
19
+ self.plot(ax=ax)
20
+
21
+ # Create an initial vertical line at the left edge of our data
22
+ # We'll move it around inside the 'motion_notify_event'
23
+ if len(self.index) == 0:
24
+ print("DataFrame is empty. Returning as-is.")
25
+ return self
26
+
27
+ # We'll place the vertical line initially at the first index
28
+ vline = ax.axvline(self.index[0], linestyle='--', color='gray')
29
+
30
+ # We'll store the two click times here
31
+ clicked_times = []
32
+
33
+ def on_mouse_move(event):
34
+ # Only move the line if we're NOT in "zoom rect" mode
35
+ if fig.canvas.manager.toolbar.mode != 'zoom rect':
36
+ if event.inaxes == ax and event.xdata is not None:
37
+ # Move the vertical line to the current mouse x
38
+ vline.set_xdata(event.xdata)
39
+ fig.canvas.draw_idle() # Redraw efficiently
40
+
41
+ def on_click(event):
42
+ # Only record the click if we're NOT in "zoom rect" mode
43
+ if fig.canvas.manager.toolbar.mode != 'zoom rect':
44
+ if event.inaxes == ax and event.xdata is not None:
45
+ # Convert Matplotlib's float date to a Python datetime
46
+ dt = mdates.num2date(event.xdata)
47
+ clicked_times.append(dt)
48
+
49
+ if len(clicked_times) == 2:
50
+ # We got two clicks—stop the event loop
51
+ fig.canvas.stop_event_loop()
52
+
53
+ # Connect the callbacks
54
+ cid_move = fig.canvas.mpl_connect("motion_notify_event", on_mouse_move)
55
+ cid_click = fig.canvas.mpl_connect("button_press_event", on_click)
56
+
57
+ # Show the plot (non‐blocking)
58
+ plt.show(block=False)
59
+
60
+ # Start an event loop that blocks until we have two clicks (or the figure is closed).
61
+ fig.canvas.start_event_loop(timeout=-1)
62
+
63
+ # Disconnect events and close the figure
64
+ fig.canvas.mpl_disconnect(cid_move)
65
+ fig.canvas.mpl_disconnect(cid_click)
66
+ plt.close(fig)
67
+
68
+ # If we didn't get two valid clicks, just return the original DataFrame
69
+ if len(clicked_times) < 2:
70
+ print("Not enough clicks were registered. Returning the original DataFrame.")
71
+ return self
72
+
73
+ # Sort the times so t0 < t1
74
+ t0, t1 = sorted(clicked_times)
75
+
76
+ # Slice the DataFrame by those two times (inclusive)
77
+ return self.loc[t0 : t1]
78
+
79
+ # Monkey‐patch the DataFrame class so any DataFrame can call df.select_xrange()
80
+ pd.DataFrame.select_xrange = select_xrange
81
+
82
+
83
+ # ----------------------------------------------------------------------------
84
+ # Example usage:
85
+ if __name__ == "__main__":
86
+ # Create a small example DataFrame with a DatetimeIndex
87
+ # dates = pd.date_range("2023-01-01", periods=30, freq="D")
88
+ # df = pd.DataFrame({"values": range(30)}, index=dates)
89
+ df = pd.read_hdf("data/daq-2025_0305_1719", key="df")
90
+ # Call our new method
91
+ subset = df.select_xrange()
92
+ print("Selected subset:\n", subset)
93
+
@@ -0,0 +1,262 @@
1
+ '''Tools for signal processing of SHM
2
+ '''
3
+
4
+ #
5
+ #
6
+ #
7
+ #
8
+
9
+ # TODO:
10
+ # - identify # of channles
11
+ # - csv or bin
12
+
13
+ # %matplotlib inline
14
+ # %matplotlib notebook
15
+ # %matplotlib widget
16
+
17
+ import struct
18
+ import datetime
19
+ from datetime import timezone
20
+ from numpy import *
21
+ import matplotlib.pyplot as pl
22
+ import matplotlib.dates as mdates
23
+
24
+ from scipy.signal import welch, detrend, cheby1, sosfiltfilt
25
+ from scipy.io import loadmat
26
+ import sys
27
+ import os
28
+
29
+ import pandas as pd
30
+ from bokeh.plotting import figure, show
31
+ from bokeh.embed import components
32
+ from bokeh.models import HoverTool
33
+ from bokeh.models import ColumnDataSource, OpenURL, TapTool
34
+ from bokeh.models import HoverTool
35
+ from bokeh.models import DatetimeTickFormatter
36
+ from bokeh.models import Range1d, LinearAxis
37
+ from bokeh.palettes import Dark2_5 as palette
38
+ import bokeh.layouts
39
+ import pandas_bokeh
40
+
41
+ #import ssi_dat
42
+ import time
43
+
44
+ class SHM:
45
+
46
+ df = []
47
+ t = []
48
+ y = []
49
+ mean = []
50
+ std = []
51
+
52
+ mp = []
53
+ nfft = 2**10
54
+ dt = []
55
+ fs = []
56
+ F = []
57
+ Pxx = []
58
+
59
+ dataPath = None
60
+ file_duration = {'acc': 600, 'wnd': 3600*24} # in seconds
61
+
62
+ db_managers = {'File':None, 'Summary': None}
63
+
64
+ def __init__(self):
65
+ pass
66
+
67
+ # LOAD ---------------------------------------------------------------------------------
68
+ def load(self, src, *args, **kwargs):
69
+ """
70
+ load(src = [raw|django-file|django-db])
71
+ """
72
+
73
+ def load_bin(fn, nch = 3):
74
+ with open(fn, 'rb') as fp:
75
+ data = fp.read()
76
+ bytes_per_sample = 4*2 + 4*nch
77
+ n = int(len(data)/bytes_per_sample)
78
+ t, y = [], []
79
+ for i in range(n):
80
+ res = list(struct.unpack('<LL' + 'f'*nch, data[i*bytes_per_sample:(i+1)*bytes_per_sample]))
81
+ t.append(res[0]*1000000 + res[1]) # in usec
82
+ y.append(res[2:])
83
+ t = pd.to_datetime(t, unit='us')
84
+ return pd.DataFrame(array(y), index = t)
85
+
86
+ def load_mat(fn, gain = 10):
87
+ mat_contents = loadmat(fn)
88
+ _keys = mat_contents.keys()
89
+ if 't' not in _keys or 'a' not in _keys:
90
+ raise Exception('loading mat failed: keys t and a are not found.')
91
+ t = mat_contents['t']
92
+ y = mat_contents['a']/10/gain # 10V per g, gain=10
93
+ return pd.DataFrame(y, index = t.flatten())
94
+
95
+ def load_django_file(nodeName, sensorType, ti, duration=None, pos='start'):
96
+ if pos == 'start':
97
+ pass
98
+ elif pos == 'centre':
99
+ ti = ti - datetime.timedelta(seconds=duration/2)
100
+ elif pos == 'end':
101
+ ti = ti - datetime.timedelta(seconds=duration)
102
+ else:
103
+ raise Exception('unknown pos variable: {}'.format(pos))
104
+ te = ti + datetime.timedelta(seconds=duration)
105
+ recs = self.db_managers['File'].filter(nodeName = nodeName)\
106
+ .filter(sensorType = sensorType)\
107
+ .filter(timestamp__gte = ti)\
108
+ .filter(timestamp__lt = te)\
109
+ .order_by('timestamp')
110
+ if len(recs) > 0:
111
+ dfs = []
112
+ for rec in recs:
113
+ dfs.append(rec.load())
114
+ return pd.concat(dfs)
115
+ else:
116
+ return None
117
+
118
+ def read_db(tableName, fields, ti, duration):
119
+ te = ti + datetime.timedelta(seconds = duration)
120
+ recs = self.db_managers[tableName].filter(timestamp__gte = ti)\
121
+ .filter(timestamp__lt = te)\
122
+ .order_by('timestamp')
123
+ t, y, columnnames = [], [], []
124
+ map = {
125
+ 'WindDir': ['WindDir'],
126
+ 'WindSpeed': ['WindSpeed'],
127
+ 'rmsd': ['rmsd_x', 'rmsd_y', 'rmsd_z', 'rmsd_tot'],
128
+ 'mean': ['mean_x', 'mean_y', 'mean_z'],
129
+ 'freq': ['freq_m11', 'freq_m12', 'freq_m21', 'freq_m22', 'freq_m3'],
130
+ 'xi': ['xi_m11', 'xi_m12', 'xi_m21', 'xi_m22', 'xi_m3'],
131
+ 'uptime': ['uptime']
132
+ }
133
+ # populate column names
134
+ for field in fields:
135
+ if field in map.keys():
136
+ columnnames += map[field]
137
+ else:
138
+ columnnames += [field]
139
+ # populate data
140
+ for idx, rec in enumerate(recs):
141
+ t.append(rec.timestamp)
142
+ row = []
143
+ for field in fields:
144
+ val = getattr(rec, field)
145
+ # print(field, val)
146
+
147
+ if isinstance(val, list):
148
+ row += val
149
+ else:
150
+ row += [val]
151
+ y.append(row)
152
+ # print(row)
153
+ # print(len(row), len(columnnames))
154
+ return pd.DataFrame(y, index = t, columns = columnnames)
155
+
156
+ if src == 'raw':
157
+ if 'filename' not in kwargs.keys():
158
+ raise Exception("filename not specified")
159
+ else:
160
+ filename = kwargs['filename']
161
+ if 'mat' in filename:
162
+ self.df = load_mat(filename)
163
+ else:
164
+ self.df = load_bin(filename)
165
+ return self.df
166
+
167
+ elif src == 'django-file':
168
+ self.df = load_django_file(*args, **kwargs)
169
+ elif src == 'django-db':
170
+ self.df = read_db(*args)
171
+ if self.df is not None:
172
+ if len(self.df.index) > 1:
173
+ dt = self.df.index[1] - self.df.index[0]
174
+ if isinstance(dt, datetime.timedelta):
175
+ dt = dt.total_seconds()
176
+ self.fs = 1/dt
177
+ else:
178
+ pass
179
+ return
180
+
181
+ # SAVE ---------------------------------------------------------------------------------
182
+
183
+ def save(self, tableName, timestamp, fields, values):
184
+ recs = self.db_managers[tableName].filter(timestamp = timestamp)
185
+ if len(recs) > 0:
186
+ rec = recs[0]
187
+ for field, value in zip(fields, values):
188
+ setattr(rec, field, value)
189
+ rec.save()
190
+ else:
191
+ raise Exception("no record found")
192
+ # SIGNAL PROC ---------------------------------------------------------------------------------
193
+
194
+ def get_statistics(self):
195
+ self.mean = self.df.mean().tolist()
196
+ self.std = self.df.std().tolist()
197
+
198
+ # def ssi(self, max_order = 100, i = 50, err = [0.01, 0.1, 0.99], max_poll = None, freq_ranges = None, **kwargs):
199
+ # ssi_dat.y = self.df.to_numpy().T
200
+ # ssi_dat.fs = self.fs
201
+ # ssi_dat.max_order = max_order
202
+ # ssi_dat.max_poll = max_poll
203
+ # ssi_dat.err = err
204
+ # if i is not None:
205
+ # ssi_dat.i = i
206
+ # ssi_dat.freq_ranges = freq_ranges
207
+ # ssi_dat.show_plots = False
208
+ #
209
+ # print('ssi_dat: i = {}, stab_criteria={}'.format(ssi_dat.i, err))
210
+ # t0 = time.time()
211
+ # ssi_dat.ssi_dat(**kwargs)
212
+ # self.ssi_dat = ssi_dat
213
+ #
214
+
215
+ # PLOT ---------------------------------------------------------------------------------
216
+
217
+ # def plot(self, **kwargs):
218
+ # # self.df.plot(**kwargs)
219
+ # pl.plot(self.t, self.y)
220
+ # pl.grid(True)
221
+
222
+ def plot_bokeh(self, **kwargs):
223
+ pd.set_option('plotting.backend', 'pandas_bokeh')
224
+ p = self.df.plot(**kwargs, show_figure = False)
225
+ p.toolbar.logo = None
226
+ script, div = components(p)
227
+ return script, div
228
+
229
+ def psd(self, plot=True, **kwargs):
230
+ # if 'figsize' in kwargs:
231
+ # figure(figsize=kwargs.get('figsize'))
232
+ # print(kwargs.get('figsize'))
233
+ # del kwargs['figsize']
234
+ f, Pxx_den = welch(self.df.to_numpy(), self.fs, nperseg=self.nfft, noverlap = fix(self.nfft*3/4), axis=0, **kwargs)
235
+ self.F = f
236
+ self.Pxx = Pxx_den
237
+ if plot:
238
+ pl.semilogy(f,sqrt(Pxx_den))
239
+ pl.xlim(0,self.fs/2)
240
+ pl.xlabel('Frequency (Hz)')
241
+ pl.ylabel('PSD g/sq(Hz)')
242
+ pl.grid(True)
243
+
244
+ def lpf(self, r, **kwargs):
245
+ sos = cheby1(8, 0.05, r, output='sos')
246
+ sos = asarray(sos, dtype = self.y.dtype)
247
+ self.y = sosfiltfilt(sos, self.y, **kwargs)
248
+
249
+
250
+
251
+ if __name__ == "__main__":
252
+ s = SHM()
253
+ s.load(src='raw', filename='data/1hr/smartply_acc1_acc_202305022200')
254
+ # s.y = s.y[:2]
255
+ s.plot()
256
+ pl.figure()
257
+ s.ssi(max_order = 100, i = 50, max_poll = 20)
258
+ pl.show()
259
+
260
+
261
+
262
+
@@ -0,0 +1,70 @@
1
+ import pandas as pd
2
+ from matplotlib.pyplot import *
3
+ from numpy import *
4
+ import matplotlib.dates as mdates
5
+
6
+
7
+
8
+ def detrend(self):
9
+ return self - self.mean()
10
+
11
+
12
+ def subset(self):
13
+ if hasattr(self, 't0') and hasattr(self, 't1'):
14
+ mask = (self.index >= self.t0.replace(tzinfo=None)) & (self.index < self.t1.replace(tzinfo=None))
15
+ return self.loc[mask, :]
16
+ else:
17
+ raise Exception('t0 or t1 doesn''t exist')
18
+
19
+
20
+ # _orig_plot = pd.DataFrame.plot
21
+
22
+ # def custom_plot(self, *args, **kwargs):
23
+ # if "figsize" not in kwargs:
24
+ # kwargs["figsize"] = (8, 4)
25
+ # elif "grid" not in kwargs:
26
+ # kwargs['grid'] = True
27
+
28
+ # # Call the original plot method
29
+ # return _orig_plot(self)(*args, **kwargs)
30
+
31
+ # pd.DataFrame.plot = custom_plot
32
+
33
+ def select(self):
34
+ fig, ax = subplots()
35
+ self.plot(ax=ax)
36
+ toolbar = fig.canvas.manager.toolbar
37
+
38
+ vline = ax.axvline(nan, linestyle="--")
39
+
40
+ def on_mouse_move(event):
41
+ if len(toolbar.mode) > 0:
42
+ vline.set_xdata(nan)
43
+ elif event.inaxes == ax and event.xdata is not None:
44
+ vline.set_xdata(event.xdata)
45
+ fig.canvas.draw_idle() # efficient redraw
46
+
47
+ def onclick(event):
48
+ nonlocal self
49
+ # event.xdata and event.ydata give the mouse click in data coordinates
50
+ # print("toolbar.mode", toolbar.mode, ' ', len(toolbar.mode))
51
+ if len(toolbar.mode) == 0:
52
+ if event.button == 1:
53
+ t0 = mdates.num2date(event.xdata)
54
+ self.t0 = t0
55
+ print("x =", event.xdata, ", y =", event.ydata)
56
+ if event.button == 3:
57
+ t1 = mdates.num2date(event.xdata)
58
+ self.t1 = t1
59
+ print("x =", event.xdata, ", y =", event.ydata)
60
+ close()
61
+
62
+ # Connect the event to the figure
63
+ fig.canvas.mpl_connect("motion_notify_event", on_mouse_move)
64
+ fig.canvas.mpl_connect('button_press_event', onclick)
65
+ show()
66
+
67
+ pd.DataFrame.detrend = detrend
68
+ pd.DataFrame.select = select
69
+ pd.DataFrame.subset = subset
70
+
@@ -0,0 +1,243 @@
1
+ #!/usr/local/bin/python3
2
+ # -*- coding: utf-8 -*-
3
+
4
+ ###########################################################################
5
+ ## Python code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
6
+ ## http://www.wxformbuilder.org/
7
+ ##
8
+ ## PLEASE DO *NOT* EDIT THIS FILE!
9
+ ###########################################################################
10
+
11
+ import wx
12
+ import wx.xrc
13
+ import wx.grid
14
+
15
+ import gettext
16
+ _ = gettext.gettext
17
+
18
+ ###########################################################################
19
+ ## Class MyFrame1
20
+ ###########################################################################
21
+
22
+ class MyFrame1 ( wx.Frame ):
23
+
24
+ def __init__( self, parent ):
25
+ wx.Frame.__init__ ( self, parent, 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 )
26
+
27
+ self.SetSizeHints( wx.DefaultSize, wx.DefaultSize )
28
+
29
+ bSizer1 = wx.BoxSizer( wx.VERTICAL )
30
+
31
+ bSizer2 = wx.BoxSizer( wx.HORIZONTAL )
32
+
33
+ self.m_staticText2 = wx.StaticText( self, wx.ID_ANY, _(u"Sensor Nodes:"), wx.DefaultPosition, wx.DefaultSize, 0 )
34
+ self.m_staticText2.Wrap( -1 )
35
+
36
+ bSizer2.Add( self.m_staticText2, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5 )
37
+
38
+ self.m_textCtrl2 = wx.TextCtrl( self, wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
39
+ bSizer2.Add( self.m_textCtrl2, 1, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5 )
40
+
41
+ self.m_staticText3 = wx.StaticText( self, wx.ID_ANY, _(u"Fs="), wx.DefaultPosition, wx.DefaultSize, 0 )
42
+ self.m_staticText3.Wrap( -1 )
43
+
44
+ bSizer2.Add( self.m_staticText3, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5 )
45
+
46
+ m_choice1Choices = [ _(u"62.5"), _(u"125") ]
47
+ self.m_choice1 = wx.Choice( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, m_choice1Choices, 0 )
48
+ self.m_choice1.SetSelection( 0 )
49
+ bSizer2.Add( self.m_choice1, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5 )
50
+
51
+ self.m_staticText4 = wx.StaticText( self, wx.ID_ANY, _(u"Hz"), wx.DefaultPosition, wx.DefaultSize, 0 )
52
+ self.m_staticText4.Wrap( -1 )
53
+
54
+ bSizer2.Add( self.m_staticText4, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5 )
55
+
56
+ self.m_button1 = wx.Button( self, wx.ID_ANY, _(u"Start DAQ"), wx.DefaultPosition, wx.DefaultSize, 0 )
57
+ bSizer2.Add( self.m_button1, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5 )
58
+
59
+ self.m_button2 = wx.Button( self, wx.ID_ANY, _(u"Stop DAQ"), wx.DefaultPosition, wx.DefaultSize, 0 )
60
+ bSizer2.Add( self.m_button2, 0, wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5 )
61
+
62
+
63
+ bSizer1.Add( bSizer2, 0, wx.EXPAND, 5 )
64
+
65
+ bSizer3 = wx.BoxSizer( wx.HORIZONTAL )
66
+
67
+ bSizer4 = wx.BoxSizer( wx.VERTICAL )
68
+
69
+ self.m_staticText21 = wx.StaticText( self, wx.ID_ANY, _(u"WiFi Mesh Status"), wx.DefaultPosition, wx.DefaultSize, 0 )
70
+ self.m_staticText21.Wrap( -1 )
71
+
72
+ bSizer4.Add( self.m_staticText21, 0, wx.ALL, 5 )
73
+
74
+ self.m_grid2 = wx.grid.Grid( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, 0 )
75
+
76
+ # Grid
77
+ self.m_grid2.CreateGrid( 5, 6 )
78
+ self.m_grid2.EnableEditing( True )
79
+ self.m_grid2.EnableGridLines( True )
80
+ self.m_grid2.EnableDragGridSize( True )
81
+ self.m_grid2.SetMargins( 0, 0 )
82
+
83
+ # Columns
84
+ self.m_grid2.SetColSize( 0, 70 )
85
+ self.m_grid2.SetColSize( 1, 100 )
86
+ self.m_grid2.SetColSize( 2, 20 )
87
+ self.m_grid2.SetColSize( 3, 40 )
88
+ self.m_grid2.SetColSize( 4, 40 )
89
+ self.m_grid2.SetColSize( 5, 45 )
90
+ self.m_grid2.EnableDragColMove( False )
91
+ self.m_grid2.EnableDragColSize( True )
92
+ self.m_grid2.SetColLabelValue( 0, _(u"Node ID") )
93
+ self.m_grid2.SetColLabelValue( 1, _(u"Status") )
94
+ self.m_grid2.SetColLabelValue( 2, _(u"L") )
95
+ self.m_grid2.SetColLabelValue( 3, _(u"RSSI") )
96
+ self.m_grid2.SetColLabelValue( 4, _(u"PPS") )
97
+ self.m_grid2.SetColLabelValue( 5, _(u"Data") )
98
+ self.m_grid2.SetColLabelSize( wx.grid.GRID_AUTOSIZE )
99
+ self.m_grid2.SetColLabelAlignment( wx.ALIGN_CENTER, wx.ALIGN_CENTER )
100
+
101
+ # Rows
102
+ self.m_grid2.EnableDragRowSize( True )
103
+ self.m_grid2.SetRowLabelSize( wx.grid.GRID_AUTOSIZE )
104
+ self.m_grid2.SetRowLabelAlignment( wx.ALIGN_CENTER, wx.ALIGN_CENTER )
105
+
106
+ # Label Appearance
107
+
108
+ # Cell Defaults
109
+ self.m_grid2.SetDefaultCellAlignment( wx.ALIGN_LEFT, wx.ALIGN_TOP )
110
+ bSizer4.Add( self.m_grid2, 1, wx.ALL|wx.EXPAND, 5 )
111
+
112
+
113
+ bSizer3.Add( bSizer4, 0, wx.EXPAND, 5 )
114
+
115
+ self.m_notebook2 = wx.Notebook( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, 0 )
116
+ self.m_panel1 = wx.Panel( self.m_notebook2, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
117
+ self.m_notebook2.AddPage( self.m_panel1, _(u"Time history plot"), True )
118
+ self.m_panel2 = wx.Panel( self.m_notebook2, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL )
119
+ self.m_notebook2.AddPage( self.m_panel2, _(u"PSD plot"), False )
120
+
121
+ bSizer3.Add( self.m_notebook2, 1, wx.ALL|wx.EXPAND, 5 )
122
+
123
+
124
+ bSizer1.Add( bSizer3, 1, wx.EXPAND, 5 )
125
+
126
+ self.m_textCtrl21 = wx.TextCtrl( self, wx.ID_ANY, _(u"\"test line 1\ntest2 line|\""), wx.DefaultPosition, wx.Size( -1,100 ), 0 )
127
+ bSizer1.Add( self.m_textCtrl21, 0, wx.ALL|wx.EXPAND, 5 )
128
+
129
+
130
+ self.SetSizer( bSizer1 )
131
+ self.Layout()
132
+
133
+ self.Centre( wx.BOTH )
134
+
135
+ # Connect Events
136
+ self.m_textCtrl2.Bind( wx.EVT_TEXT, self.test )
137
+
138
+ def __del__( self ):
139
+ pass
140
+
141
+
142
+ # Virtual event handlers, override them in your derived class
143
+ def test( self, event ):
144
+ event.Skip()
145
+
146
+ import wx
147
+ import wx.lib.agw.aui as aui
148
+ import wx.lib.mixins.inspection as wit
149
+ from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
150
+ from matplotlib.backends.backend_wxagg import \
151
+ NavigationToolbar2WxAgg as NavigationToolbar
152
+ from matplotlib.figure import Figure
153
+
154
+ class Plot(wx.Panel):
155
+ def __init__(self, parent, id=-1, dpi=None, **kwargs):
156
+ super().__init__(parent, id=id, **kwargs)
157
+ self.figure = Figure(dpi=dpi, figsize=(2, 2))
158
+ self.canvas = FigureCanvas(self, -1, self.figure)
159
+ self.toolbar = NavigationToolbar(self.canvas)
160
+ self.toolbar.Realize()
161
+
162
+ sizer = wx.BoxSizer(wx.VERTICAL)
163
+ sizer.Add(self.canvas, 1, wx.EXPAND)
164
+ sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND)
165
+ self.SetSizer(sizer)
166
+
167
+ class PlotNotebook(wx.Panel):
168
+ def __init__(self, parent, id=-1):
169
+ super().__init__(parent, id=id)
170
+ self.nb = aui.AuiNotebook(self)
171
+ sizer = wx.BoxSizer()
172
+ sizer.Add(self.nb, 1, wx.EXPAND)
173
+ self.SetSizer(sizer)
174
+
175
+ def add(self, name="plot"):
176
+ page = Plot(self.nb)
177
+ self.nb.AddPage(page, name)
178
+ return page.figure
179
+
180
+
181
+ import wx.grid as gridlib
182
+ import configparser
183
+ import os
184
+
185
+ CONFIG_FILE = 'config.ini'
186
+
187
+ def save_config(options):
188
+ config = configparser.ConfigParser()
189
+
190
+ config['Settings'] = {
191
+ 'option1': options['option1'],
192
+ 'option2': options['option2']
193
+ }
194
+
195
+ with open(CONFIG_FILE, 'w') as configfile:
196
+ config.write(configfile)
197
+
198
+ def load_config():
199
+ config = configparser.ConfigParser()
200
+
201
+ if not os.path.exists(CONFIG_FILE):
202
+ # Return default options if config file doesn't exist
203
+ return {
204
+ 'option1': 'default_value1',
205
+ 'option2': 'default_value2'
206
+ }
207
+
208
+ config.read(CONFIG_FILE)
209
+ options = {
210
+ 'option1': config.get('Settings', 'option1', fallback='default_value1'),
211
+ 'option2': config.get('Settings', 'option2', fallback='default_value2')
212
+ }
213
+
214
+ return options
215
+
216
+ app = wx.App()
217
+ # window = wx.Frame(None, title = "wxPython Frame", size = (300,200))
218
+ frame1 = MyFrame1(None)
219
+
220
+
221
+ fig1 = Plot(frame1.m_panel1)
222
+ # plotter = PlotNotebook(frame1.m_notebook2)
223
+ axes1 = fig1.figure.add_subplot()
224
+ axes1.plot([1, 2, 3], [2, 1, 4])
225
+ fig2 = Plot(frame1.m_panel2)
226
+ axes2 = fig2.figure.add_subplot()
227
+ axes2.plot([1, 2, 3, 4, 5], [2, 1, 4, 2, 3])
228
+
229
+ canvas = FigureCanvas(frame1.m_panel1, -1, fig1.figure)
230
+ sizer = wx.BoxSizer(wx.VERTICAL)
231
+ sizer.Add(canvas, 1, wx.EXPAND)
232
+
233
+ # Set the sizer for the panel
234
+ frame1.m_panel1.SetSizer(sizer)
235
+
236
+ # Change the background color of cell (1, 1)
237
+ attr = gridlib.GridCellAttr()
238
+ attr.SetBackgroundColour(wx.Colour(255, 255, 0)) # Yellow
239
+ frame1.m_grid2.SetAttr(1, 1, attr)
240
+
241
+
242
+ frame1.Show(True)
243
+ app.MainLoop()