nt25 0.1.1__py3-none-any.whl → 0.1.3__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.
nt25/__init__.py CHANGED
@@ -4,4 +4,6 @@ from .lib import fio, calc, draw
4
4
  from .lib.draw import DType
5
5
 
6
6
  __version__ = meta.version(str(__package__))
7
- __all__ = ('__version__', 'fio', 'calc', 'draw', 'DType')
7
+ __data_path__ = __file__.replace('__init__.py', 'data')
8
+
9
+ __all__ = ('__version__', '__data_path__', 'fio', 'calc', 'draw', 'DType')
nt25/data/test.xlsx ADDED
Binary file
nt25/lib/calc.py CHANGED
@@ -88,11 +88,11 @@ def solveEq(eq, output=False, foo='solve'):
88
88
  if 'I' in sol:
89
89
  continue
90
90
 
91
- func = _genFunc(foo, 'y, x1=0', sol)
91
+ func = _genFunc(foo, 'y, x1=0', sol.replace('y', 'y[0]'))
92
92
  s4e = re.sub(r'([-]?\d*\.\d+)', lambda m: str2e(m.group(0)), sol)
93
93
 
94
94
  if output:
95
- print(f'{foo}: {eq}\n x0 = {s4e}\n')
95
+ print(f'{foo}: {eq}\n\n x0 = {s4e}\n')
96
96
 
97
97
  real.append({
98
98
  'org': eq,
nt25/lib/draw.py CHANGED
@@ -3,23 +3,61 @@ from random import sample
3
3
 
4
4
  import numpy as np
5
5
 
6
- from matplotlib.axes import Axes
7
6
  from matplotlib import pyplot as plot
7
+ from matplotlib.axes import Axes
8
+ from mpl_toolkits.mplot3d import Axes3D
9
+
10
+ from . import calc
8
11
 
9
12
  # import matplotlib.animation as animation
10
13
 
11
14
 
12
- FONTS = ['PingFang SC', 'Microsoft YaHei', 'Arial']
15
+ FONTS = [
16
+ 'Microsoft YaHei',
17
+ 'PingFang SC',
18
+ 'Arial Unicode MS',
19
+ 'Noto Sans CJK SC',
20
+ 'Arial'
21
+ ]
22
+
13
23
  COLORS = ['blue', 'red', 'orange', 'black', 'pink']
14
24
 
25
+ REFS = []
26
+
27
+
28
+ class DType(Enum):
29
+ dot = 1,
30
+ line = 2,
31
+ func = 3,
32
+ dot3d = 4,
33
+ wireframe = 5,
34
+ surface = 6,
35
+
36
+
37
+ def onClose(event):
38
+ global REFS
39
+
40
+ for r in REFS:
41
+ del r['figure']
42
+ del r['subplot']
43
+
44
+ REFS.clear()
45
+
46
+
47
+ def _getPlot(ref, pos, is3D):
48
+ # def _getPlot(ref, pos, is3D) -> Axes | Axes3D:
49
+ global REFS
15
50
 
16
- def _getPlot(ref, pos, font='Roboto') -> Axes:
17
51
  if 'figure' not in ref:
18
- ref['figure'] = plot.figure()
19
- plot.rcParams['font.sans-serif'] = [font] + FONTS
20
- # plot.rcParams['font.sans-serif'] = ['Arial']
52
+ fig = plot.figure()
53
+ fig.canvas.mpl_connect('close_event', onClose)
54
+
55
+ plot.rcParams['font.sans-serif'] = FONTS
21
56
  plot.rcParams['axes.unicode_minus'] = False
22
57
 
58
+ ref['figure'] = fig
59
+ REFS.append(ref)
60
+
23
61
  if 'subplot' not in ref:
24
62
  ref['subplot'] = {}
25
63
 
@@ -27,7 +65,8 @@ def _getPlot(ref, pos, font='Roboto') -> Axes:
27
65
  sub = ref['subplot']
28
66
 
29
67
  if pos not in sub:
30
- sub[pos] = fig.add_subplot(pos)
68
+ sub[pos] = fig.add_subplot(
69
+ pos, projection='3d') if is3D else fig.add_subplot(pos)
31
70
 
32
71
  return sub[pos]
33
72
 
@@ -41,75 +80,70 @@ def _genList(refer: list, length, random=False):
41
80
  return r[:length]
42
81
 
43
82
 
44
- def _coord(ref, X, Y, color, pos, randomColor, method, *args, **kwargs):
45
- Xa = np.array(X)
46
- Ya = np.array(Y)
83
+ def _genParam(pIn, pDefault, count):
84
+ if pIn is None:
85
+ pIn = pDefault
47
86
 
48
- if Xa.shape != Ya.shape:
49
- print(f"bad shape {Xa.shape} != {Ya.shape}")
50
- return
87
+ if count == 1:
88
+ if isinstance(pIn, (list, tuple)):
89
+ pIn = pIn[0]
51
90
 
52
- count = 1
53
- # count = Xa.shape[0] if len(Xa.shape) > 1 else 1
91
+ elif len(pIn) != count:
92
+ # print(f"bad len {len(pIn)} != {count}")
93
+ pIn = None
54
94
 
55
- if len(Xa.shape) > 1:
56
- count = Xa.shape[0]
57
- if count == 1:
58
- X = X[0]
59
- Y = Y[0]
95
+ return pIn
60
96
 
61
- if color is None:
62
- color = _genList(COLORS, count, random=randomColor)
63
97
 
64
- if count == 1:
65
- if isinstance(color, (list, tuple)):
66
- color = color[0]
67
- elif len(color) != count:
68
- print(f"bad color.len {len(color)} != {count}")
69
- return
98
+ def title(ref, title, pos=111, x=None, y=None, z=None):
99
+ result = False
70
100
 
71
- if pos is None:
72
- pos = [111] * count
101
+ if 'subplot' in ref:
102
+ sub = ref['subplot']
73
103
 
74
- if count == 1:
75
- if isinstance(pos, (list, tuple)):
76
- pos = pos[0]
77
- elif len(pos) != count:
78
- print(f"bad pos.len {len(pos)} != {count}")
79
- return
104
+ if pos in sub:
105
+ result = True
106
+ sub[pos].set_title(title)
80
107
 
81
- if count > 1 and isinstance(pos, list):
82
- for i in range(count):
83
- p = _getPlot(ref, pos[i])
84
- method(p, X[i], Y[i], color=color[i], *args, **kwargs)
85
- else:
86
- p = _getPlot(ref, pos)
87
- method(p, X, Y, color=color, *args, **kwargs)
108
+ if x:
109
+ sub[pos].set_xlabel(x)
88
110
 
89
- return ref
111
+ if y:
112
+ sub[pos].set_ylabel(y)
90
113
 
114
+ if z:
115
+ sub[pos].set_zlabel(z)
91
116
 
92
- class DType(Enum):
93
- scatter = 1,
94
- line = 2,
95
- func = 3,
117
+ return result
118
+
119
+
120
+ def _gen3DXY(X, Y, extend=0.2):
121
+ dx = (max(X) - min(X)) * extend
122
+ d0 = np.linspace(min(X) - dx, max(X) + dx)
123
+
124
+ dy = (max(Y) - min(Y)) * extend
125
+ d1 = np.linspace(min(Y) - dy, max(Y) + dy)
96
126
 
127
+ return np.meshgrid(d0, d1)
128
+
129
+
130
+ def draw(type=DType.dot, X=None, Y=None, Z=None, Func=None, min=None, max=None,
131
+ ref=None, pos=None, label=None, color=None, randomColor=False,
132
+ labelLocation='upper left', *args, **kwargs):
97
133
 
98
- def d2d(type=DType.scatter, X=None, Y=None, Func=None, min=None, max=None,
99
- ref=None, color=None, pos=None, randomColor=False, show=False,
100
- *args, **kwargs):
101
134
  if ref is None:
102
135
  ref = {}
103
136
 
104
- match type:
105
- case DType.scatter:
106
- func = Axes.scatter
137
+ is3D = False
138
+ method = Axes.scatter
107
139
 
140
+ match type:
108
141
  case DType.line:
109
- func = Axes.plot
142
+ method = Axes.plot
110
143
 
111
144
  case DType.func:
112
- func = Axes.plot
145
+ method = Axes.plot
146
+
113
147
  if Func is not None and min is not None and max is not None:
114
148
  if callable(Func):
115
149
  Func = (Func,)
@@ -124,15 +158,116 @@ def d2d(type=DType.scatter, X=None, Y=None, Func=None, min=None, max=None,
124
158
  X.append(dx)
125
159
  Y.append([Func[i]([x]) for x in dx])
126
160
 
127
- ref = _coord(ref, X, Y, color=color, pos=pos, randomColor=randomColor,
128
- method=func, *args, **kwargs)
161
+ case DType.dot3d:
162
+ is3D = True
163
+ method = Axes3D.scatter
164
+
165
+ case DType.wireframe:
166
+ is3D = True
167
+ # rstride=2, cstride=2
168
+ method = Axes3D.plot_wireframe
129
169
 
130
- if show:
131
- plot.show()
170
+ case DType.surface:
171
+ is3D = True
172
+ # cmap='Pastel2_r', antialiased=True
173
+ method = Axes3D.plot_surface
174
+
175
+ if X is None or Y is None:
176
+ print("no X/Y to draw")
177
+ return
178
+
179
+ Xa = np.array(X)
180
+ Ya = np.array(Y)
181
+
182
+ if Xa.shape != Ya.shape:
183
+ print(f"bad shape {Xa.shape} != {Ya.shape}")
184
+ return
185
+
186
+ if type == DType.dot3d:
187
+ if Z is None:
188
+ print("Z cannot be None")
189
+ return
190
+
191
+ Za = np.array(Z)
192
+ if Xa.shape != Za.shape:
193
+ print(f"bad shape {Xa.shape} == {Ya.shape} != {Za.shape}")
194
+ return
195
+
196
+ elif is3D:
197
+ if Z is not None and Func is None:
198
+ Za = np.array(Z)
199
+ if Xa.shape != Za.shape:
200
+ print(f"bad shape {Xa.shape} == {Ya.shape} != {Za.shape}")
201
+ return
202
+
203
+ F = calc.xn2y([X, Y], Z, degree=3)
204
+ Func = F['func']
205
+
206
+ if Func is None:
207
+ print("Func cannot be None")
208
+ return
209
+
210
+ if callable(Func):
211
+ X, Y = _gen3DXY(X, Y)
212
+ Z = Func([X, Y])
213
+ else:
214
+ print("Func need callable")
215
+ return
216
+
217
+ count = 1
218
+ # count = Xa.shape[0] if len(Xa.shape) > 1 else 1
219
+
220
+ if len(Xa.shape) > 1:
221
+ count = Xa.shape[0]
222
+ if count == 1:
223
+ X = X[0]
224
+ Y = Y[0]
225
+
226
+ if Z is not None and isinstance(Z, list):
227
+ Z = Z[0]
228
+
229
+ if is3D and type != DType.dot3d:
230
+ count = 1
231
+
232
+ pos = _genParam(pos, [111] * count, count)
233
+ label = _genParam(label, [None] * count, count)
234
+ color = _genParam(color, _genList(COLORS, count, random=randomColor), count)
235
+
236
+ if pos is None or color is None:
237
+ print("bad length")
238
+ return
239
+
240
+ if count == 1:
241
+ p = _getPlot(ref, pos, is3D)
242
+ _draw(method, p, type, X, Y, Z, label=label, color=color, *args, **kwargs)
243
+
244
+ elif (isinstance(pos, list) and
245
+ isinstance(label, list) and isinstance(color, list)):
246
+
247
+ for i in range(count):
248
+ p = _getPlot(ref, pos[i], is3D)
249
+ _draw(method, p, type, X[i], Y[i], Z[i]
250
+ if isinstance(Z, list) else None, label, color, *args, **kwargs)
251
+
252
+ if label is not None:
253
+ plot.legend(loc=labelLocation)
132
254
 
133
255
  return ref
134
256
 
135
257
 
258
+ def _draw(method, p, type, x, y, z, label, color, *args, **kwargs):
259
+ match type:
260
+ case DType.dot3d | DType.wireframe:
261
+ method(p, x, y, z, label=label, color=color,
262
+ antialiased=True, *args, **kwargs)
263
+
264
+ case DType.surface:
265
+ method(p, x, y, z, label=label, antialiased=True, *args, **kwargs)
266
+
267
+ case _:
268
+ method(p, x, y, label=label, color=color, *args, **kwargs)
269
+
270
+
136
271
  def show():
137
272
  plot.show()
138
273
 
nt25/main.py CHANGED
@@ -1,4 +1,5 @@
1
- from nt25 import fio, calc, draw, DType, __version__
1
+ import os
2
+ from nt25 import fio, calc, draw, DType, __version__, __data_path__
2
3
 
3
4
  # import timeit
4
5
  # timeit.timeit('', number=100, globals=globals())
@@ -8,14 +9,16 @@ def main():
8
9
  print(f"Hello from {__package__}({__version__})! ")
9
10
 
10
11
  # [Neo] some file I/O: csv, xlsx
12
+ os.makedirs('output', exist_ok=True)
13
+
11
14
  fio.saveCSV({
12
15
  'Name': ['Alice', 'Bob', 'Charlie'],
13
16
  'Age': [25.2, 30, 35],
14
17
  'City': ['New York', 'Los Angeles', 'Chicago']
15
- }, "out.csv", colsInline=False)
18
+ }, "output/out.csv")
16
19
 
17
- data = fio.getXlsx('ds/qs.xlsx')
18
- fio.saveCSV(data, "out2.csv")
20
+ data = fio.getXlsx(__data_path__ + '/test.xlsx')
21
+ fio.saveCSV(data, "output/out2.csv")
19
22
 
20
23
  h = data[0]
21
24
  s = data[1]
@@ -27,27 +30,47 @@ def main():
27
30
  print(c, ce)
28
31
 
29
32
  foo = calc.xn2y(h, v, degree=3, output=True)
30
- bar = calc.solveEq(foo['eq'])
33
+ bar = calc.solveEq(foo['eq'], output=False)
31
34
 
32
35
  func = foo['func']
33
36
  bfunc = bar[0]['func']
34
37
 
35
38
  Y = range(1000, 2000, 200)
36
- X = [bfunc(y) for y in Y]
39
+ X = [bfunc([y]) for y in Y]
40
+
41
+ # [Neo] draw with title, data dots
42
+ ref = draw.draw(X=h, Y=v)
43
+ draw.title(ref, "title", x='xlabel', y='ylabel')
44
+ draw.draw(type=DType.dot, X=X, Y=Y, ref=ref, color='red', s=120)
45
+ draw.show()
46
+
47
+ # [Neo] draw with function, split in two
48
+ draw.draw(type=DType.func, Func=func, min=40, max=60, ref=ref, pos=121,
49
+ label='func', color='red')
50
+ draw.draw(type=DType.func, Func=bfunc, min=0, max=4000, ref=ref, pos=122,
51
+ label='bfunc', labelLocation='upper right')
52
+ draw.show()
53
+
54
+ # [Neo] draw with 3d dots, and function in surface
55
+ ref = draw.draw(DType.dot3d, X=h, Y=s, Z=v, color='red', pos=121)
56
+ draw.title(ref, "三维", pos=121)
57
+
58
+ foo = calc.xn2y([h, s], v, degree=3, output=True)
59
+ func = foo['func']
37
60
 
38
- # [Neo] draw 2d with types
39
- ref = {}
40
- draw.d2d(X=h, Y=v, ref=ref)
41
- draw.d2d(type=DType.scatter, X=X, Y=Y, ref=ref, color='red', s=120)
42
- draw.d2d(type=DType.func, Func=func, min=40, max=60, ref=ref, color='red')
61
+ # change default color
62
+ draw.draw(DType.surface, h, s, Func=func,
63
+ ref=ref, pos=121, cmap='Pastel2_r',)
64
+ # auto-gen surface with dots, change default gird size
65
+ draw.draw(DType.wireframe, h, s, v,
66
+ ref=ref, pos=122, rstride=2, cstride=2)
43
67
  draw.show()
44
68
 
45
- # [Neo] and 3d calcs
46
- foo = calc.xn2y([h, s], v, degree=3, output=False)
69
+ # [Neo] and 3d solve equal
47
70
  bar = calc.solveEq(foo['eq'], output=True)
48
71
 
49
72
  if len(bar) > 0:
50
- print('s> 750, 1.5 ~', bar[0]['func'](y=750, x1=1.5))
73
+ print(f'solveEq(750, 1.5) ~ {bar[0]['func'](y=[750], x1=1.5):.4f}')
51
74
 
52
75
 
53
76
  if __name__ == "__main__":
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nt25
3
- Version: 0.1.1
3
+ Version: 0.1.3
4
4
  Summary: Neo's Tools of Python
5
- Requires-Python: >=3.13
5
+ Requires-Python: >=3.10
6
6
  Requires-Dist: matplotlib>=3.10.6
7
7
  Requires-Dist: openpyxl>=3.1.5
8
8
  Requires-Dist: pandas>=2.3.2
@@ -18,8 +18,11 @@ Neo's Tools of Python in 2025
18
18
 
19
19
  - [x] fio
20
20
  - [x] calc
21
- - [x] draw with 2d
22
- - [ ] draw with 3d
21
+ - [x] draw
22
+ - [ ] mysql
23
+ - [ ] redis
24
+ - [ ] maptrans
25
+ - [ ] ttp
23
26
 
24
27
  ## scripts from init
25
28
 
@@ -0,0 +1,10 @@
1
+ nt25/__init__.py,sha256=oIVhU2wegSHArUmypHr3nXQa8RRtH5TBZgRdRNN-OEw,274
2
+ nt25/main.py,sha256=nVzuGx8PaxDU-QbLmVtAvDkfEFX5Z5g0xE0CWf9EwBA,2098
3
+ nt25/data/test.xlsx,sha256=7C0JDS-TLm_KmjnKtfeajkpwGKSUhcLdr2W2UFUxAgM,10542
4
+ nt25/lib/calc.py,sha256=3X3k9jisSjRP7OokSdKvoVo4IIOzk2efexW8z1gMo-w,2265
5
+ nt25/lib/draw.py,sha256=OKTlkkNVUz_LGBA9Gk7fjcnbbbl7e_hT8nWKkcfeg2k,5642
6
+ nt25/lib/fio.py,sha256=WvHpG6QYR1NE19Ss3Sy2FdajTxibX5SVW3PyC5Y5Krk,2525
7
+ nt25-0.1.3.dist-info/METADATA,sha256=4UAR18xVAWpD1hw-6FsB9F5dEl7IYD29eowXtaLo_X8,528
8
+ nt25-0.1.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
9
+ nt25-0.1.3.dist-info/entry_points.txt,sha256=mApCFA2DAwrQrcWa5JqcKq7lPzogm_Yi4EejBUo-Of8,40
10
+ nt25-0.1.3.dist-info/RECORD,,
@@ -1,9 +0,0 @@
1
- nt25/__init__.py,sha256=3pJhB9zM_qRUTiAj98xwwd-8muwSgGC0-Sd_CEYi4Tc,200
2
- nt25/main.py,sha256=TkgLVeEm3GENii-JVUhLVIfO31N9QLjwkRbELxj1k4A,1256
3
- nt25/lib/calc.py,sha256=FHPHtHw7Mcm3PlVoC1c3ghpapZe0GhPVG5-mmfHkDaw,2242
4
- nt25/lib/draw.py,sha256=5llf6Q3ljBNBkIEphZzL7Xv0ZZu8i2CTBHYmRzH84lU,3020
5
- nt25/lib/fio.py,sha256=WvHpG6QYR1NE19Ss3Sy2FdajTxibX5SVW3PyC5Y5Krk,2525
6
- nt25-0.1.1.dist-info/METADATA,sha256=b9YUoAt5tU5DL5DfstJUFV175yQLrCLjn-o6hbya_gs,506
7
- nt25-0.1.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
8
- nt25-0.1.1.dist-info/entry_points.txt,sha256=mApCFA2DAwrQrcWa5JqcKq7lPzogm_Yi4EejBUo-Of8,40
9
- nt25-0.1.1.dist-info/RECORD,,
File without changes