nt25 0.1.1__py3-none-any.whl → 0.1.2__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 +3 -1
- nt25/lib/calc.py +1 -1
- nt25/lib/draw.py +195 -60
- nt25/main.py +32 -12
- nt25/scripts/test3d.py +11 -0
- {nt25-0.1.1.dist-info → nt25-0.1.2.dist-info}/METADATA +7 -4
- nt25-0.1.2.dist-info/RECORD +10 -0
- nt25-0.1.1.dist-info/RECORD +0 -9
- {nt25-0.1.1.dist-info → nt25-0.1.2.dist-info}/WHEEL +0 -0
- {nt25-0.1.1.dist-info → nt25-0.1.2.dist-info}/entry_points.txt +0 -0
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
|
-
|
7
|
+
__samples_path__ = __file__.replace('__init__.py', 'samples')
|
8
|
+
|
9
|
+
__all__ = ('__version__', '__samples_path__', 'fio', 'calc', 'draw', 'DType')
|
nt25/lib/calc.py
CHANGED
@@ -88,7 +88,7 @@ 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:
|
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 = [
|
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
|
-
|
19
|
-
|
20
|
-
|
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(
|
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
|
45
|
-
|
46
|
-
|
83
|
+
def _genParam(pIn, pDefault, count):
|
84
|
+
if pIn is None:
|
85
|
+
pIn = pDefault
|
47
86
|
|
48
|
-
if
|
49
|
-
|
50
|
-
|
87
|
+
if count == 1:
|
88
|
+
if isinstance(pIn, (list, tuple)):
|
89
|
+
pIn = pIn[0]
|
51
90
|
|
52
|
-
|
53
|
-
|
91
|
+
elif len(pIn) != count:
|
92
|
+
# print(f"bad len {len(pIn)} != {count}")
|
93
|
+
pIn = None
|
54
94
|
|
55
|
-
|
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
|
-
|
65
|
-
|
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
|
72
|
-
|
101
|
+
if 'subplot' in ref:
|
102
|
+
sub = ref['subplot']
|
73
103
|
|
74
|
-
|
75
|
-
|
76
|
-
pos
|
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
|
-
|
82
|
-
|
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
|
-
|
111
|
+
if y:
|
112
|
+
sub[pos].set_ylabel(y)
|
90
113
|
|
114
|
+
if z:
|
115
|
+
sub[pos].set_zlabel(z)
|
91
116
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
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
|
-
|
105
|
-
|
106
|
-
func = Axes.scatter
|
137
|
+
is3D = False
|
138
|
+
method = Axes.scatter
|
107
139
|
|
140
|
+
match type:
|
108
141
|
case DType.line:
|
109
|
-
|
142
|
+
method = Axes.plot
|
110
143
|
|
111
144
|
case DType.func:
|
112
|
-
|
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
|
-
|
128
|
-
|
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
|
-
|
131
|
-
|
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,4 @@
|
|
1
|
-
from nt25 import fio, calc, draw, DType, __version__
|
1
|
+
from nt25 import fio, calc, draw, DType, __version__, __samples_path__
|
2
2
|
|
3
3
|
# import timeit
|
4
4
|
# timeit.timeit('', number=100, globals=globals())
|
@@ -14,7 +14,7 @@ def main():
|
|
14
14
|
'City': ['New York', 'Los Angeles', 'Chicago']
|
15
15
|
}, "out.csv", colsInline=False)
|
16
16
|
|
17
|
-
data = fio.getXlsx('
|
17
|
+
data = fio.getXlsx(__samples_path__ + '/test.xlsx')
|
18
18
|
fio.saveCSV(data, "out2.csv")
|
19
19
|
|
20
20
|
h = data[0]
|
@@ -27,27 +27,47 @@ def main():
|
|
27
27
|
print(c, ce)
|
28
28
|
|
29
29
|
foo = calc.xn2y(h, v, degree=3, output=True)
|
30
|
-
bar = calc.solveEq(foo['eq'])
|
30
|
+
bar = calc.solveEq(foo['eq'], output=False)
|
31
31
|
|
32
32
|
func = foo['func']
|
33
33
|
bfunc = bar[0]['func']
|
34
34
|
|
35
35
|
Y = range(1000, 2000, 200)
|
36
|
-
X = [bfunc(y) for y in Y]
|
36
|
+
X = [bfunc([y]) for y in Y]
|
37
37
|
|
38
|
-
# [Neo] draw
|
39
|
-
ref =
|
40
|
-
draw.
|
41
|
-
draw.
|
42
|
-
draw.d2d(type=DType.func, Func=func, min=40, max=60, ref=ref, color='red')
|
38
|
+
# [Neo] draw with title, data dots
|
39
|
+
ref = draw.draw(X=h, Y=v)
|
40
|
+
draw.title(ref, "title", x='xlabel', y='ylabel')
|
41
|
+
draw.draw(type=DType.dot, X=X, Y=Y, ref=ref, color='red', s=120)
|
43
42
|
draw.show()
|
44
43
|
|
45
|
-
# [Neo]
|
46
|
-
|
44
|
+
# [Neo] draw with function, split in two
|
45
|
+
draw.draw(type=DType.func, Func=func, min=40, max=60, ref=ref, pos=121,
|
46
|
+
label='func', color='red')
|
47
|
+
draw.draw(type=DType.func, Func=bfunc, min=0, max=4000, ref=ref, pos=122,
|
48
|
+
label='bfunc', labelLocation='upper right')
|
49
|
+
draw.show()
|
50
|
+
|
51
|
+
# [Neo] draw with 3d dots, and function in surface
|
52
|
+
ref = draw.draw(DType.dot3d, X=h, Y=s, Z=v, color='red', pos=121)
|
53
|
+
draw.title(ref, "三维", pos=121)
|
54
|
+
|
55
|
+
foo = calc.xn2y([h, s], v, degree=3, output=True)
|
56
|
+
func = foo['func']
|
57
|
+
|
58
|
+
# change default color
|
59
|
+
draw.draw(DType.surface, h, s, Func=func,
|
60
|
+
ref=ref, pos=121, cmap='Pastel2_r',)
|
61
|
+
# auto-gen surface with dots, change default gird size
|
62
|
+
draw.draw(DType.wireframe, h, s, v,
|
63
|
+
ref=ref, pos=122, rstride=2, cstride=2)
|
64
|
+
draw.show()
|
65
|
+
|
66
|
+
# [Neo] and 3d solve equal
|
47
67
|
bar = calc.solveEq(foo['eq'], output=True)
|
48
68
|
|
49
69
|
if len(bar) > 0:
|
50
|
-
print('s> 750, 1.5 ~', bar[0]['func'](y=750, x1=1.5))
|
70
|
+
print('s> 750, 1.5 ~', bar[0]['func'](y=[750], x1=1.5))
|
51
71
|
|
52
72
|
|
53
73
|
if __name__ == "__main__":
|
nt25/scripts/test3d.py
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
from nt25 import fio, draw, DType
|
2
|
+
|
3
|
+
csv = fio.getCSV('ds/92.csv', width=11, startLine=1)
|
4
|
+
if isinstance(csv, list):
|
5
|
+
P = csv[0]
|
6
|
+
Pa = csv[1]
|
7
|
+
R = csv[9]
|
8
|
+
|
9
|
+
ref = draw.draw(DType.dot3d, P, Pa, R)
|
10
|
+
draw.draw(DType.wireframe, P, Pa, R, ref=ref, color='orange')
|
11
|
+
draw.show()
|
@@ -1,8 +1,8 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: nt25
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.2
|
4
4
|
Summary: Neo's Tools of Python
|
5
|
-
Requires-Python: >=3.
|
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
|
22
|
-
- [ ]
|
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=1KKnRfR3-cwA0HPzYYIr4Y3MfHGIcV33gHGlK5j1qOo,283
|
2
|
+
nt25/main.py,sha256=H7rpN_DHcd6vbKWjO0mxxETMC7t_u_4Qp-XBP_hSH7A,2046
|
3
|
+
nt25/lib/calc.py,sha256=GKDuC8k1v4lwxFThyZx7CGNjPHeyVH3FTgNU2zCWJ44,2263
|
4
|
+
nt25/lib/draw.py,sha256=OKTlkkNVUz_LGBA9Gk7fjcnbbbl7e_hT8nWKkcfeg2k,5642
|
5
|
+
nt25/lib/fio.py,sha256=WvHpG6QYR1NE19Ss3Sy2FdajTxibX5SVW3PyC5Y5Krk,2525
|
6
|
+
nt25/scripts/test3d.py,sha256=DIvCaUc2NoALTxu4E9h4oO9dvb_C2XI0R3QzR_PXR3c,274
|
7
|
+
nt25-0.1.2.dist-info/METADATA,sha256=m2_4PF9bcl7BkQz6ICj8B1RjpGc6uHG3KxGwbzuQPDI,528
|
8
|
+
nt25-0.1.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
9
|
+
nt25-0.1.2.dist-info/entry_points.txt,sha256=mApCFA2DAwrQrcWa5JqcKq7lPzogm_Yi4EejBUo-Of8,40
|
10
|
+
nt25-0.1.2.dist-info/RECORD,,
|
nt25-0.1.1.dist-info/RECORD
DELETED
@@ -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
|
File without changes
|