nt25 0.1.0__tar.gz → 0.1.2__tar.gz

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.
@@ -1,10 +1,10 @@
1
- root = true
2
-
3
- [*]
4
- indent_style = space
5
- indent_size = 2
6
- insert_final_newline = true
7
- trim_trailing_whitespace = true
8
- end_of_line = lf
9
- charset = utf-8
10
- max_line_length = 88
1
+ root = true
2
+
3
+ [*]
4
+ indent_style = space
5
+ indent_size = 2
6
+ insert_final_newline = true
7
+ trim_trailing_whitespace = true
8
+ end_of_line = lf
9
+ charset = utf-8
10
+ max_line_length = 88
@@ -1,2 +1,2 @@
1
- [flake8]
2
- indent-size = 2
1
+ [flake8]
2
+ indent-size = 2
@@ -1,29 +1,29 @@
1
- name: Publish
2
-
3
- on:
4
- push:
5
- tags: ["*"]
6
-
7
- jobs:
8
- pypi-publish:
9
- runs-on: ubuntu-latest
10
-
11
- permissions:
12
- id-token: write
13
-
14
- environment:
15
- name: publish
16
- url: https://pypi.org/p/ntpy
17
-
18
- steps:
19
- - name: Checkout
20
- uses: actions/checkout@v4
21
-
22
- - name: Setup
23
- uses: astral-sh/setup-uv@v6
24
-
25
- - name: Build
26
- run: uv build
27
-
28
- - name: Publish
29
- uses: pypa/gh-action-pypi-publish@release/v1
1
+ name: Publish
2
+
3
+ on:
4
+ push:
5
+ tags: ["*"]
6
+
7
+ jobs:
8
+ pypi-publish:
9
+ runs-on: ubuntu-latest
10
+
11
+ permissions:
12
+ id-token: write
13
+
14
+ environment:
15
+ name: publish
16
+ url: https://pypi.org/p/nt25
17
+
18
+ steps:
19
+ - name: Checkout
20
+ uses: actions/checkout@v4
21
+
22
+ - name: Setup
23
+ uses: astral-sh/setup-uv@v6
24
+
25
+ - name: Build
26
+ run: uv build
27
+
28
+ - name: Publish
29
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -10,6 +10,12 @@ wheels/
10
10
  uv.lock
11
11
  .venv
12
12
 
13
+ # package
14
+ *.spec
15
+
16
+ # dataset
13
17
  ds/
14
18
  *.csv
15
19
  *.xlsx
20
+
21
+
@@ -0,0 +1,3 @@
1
+ {
2
+ "cSpell.words": ["bfunc"]
3
+ }
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nt25
3
- Version: 0.1.0
3
+ Version: 0.1.2
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
@@ -10,15 +10,19 @@ Requires-Dist: scikit-learn>=1.7.1
10
10
  Requires-Dist: sympy>=1.14.0
11
11
  Description-Content-Type: text/markdown
12
12
 
13
- # NT.py
13
+ # nt25.py
14
14
 
15
- Neo's Tools of Python
15
+ Neo's Tools of Python in 2025
16
16
 
17
17
  ## plans
18
18
 
19
19
  - [x] fio
20
20
  - [x] calc
21
- - [ ] draw with 3d
21
+ - [x] draw
22
+ - [ ] mysql
23
+ - [ ] redis
24
+ - [ ] maptrans
25
+ - [ ] ttp
22
26
 
23
27
  ## scripts from init
24
28
 
@@ -1,22 +1,26 @@
1
- # NT.py
2
-
3
- Neo's Tools of Python
4
-
5
- ## plans
6
-
7
- - [x] fio
8
- - [x] calc
9
- - [ ] draw with 3d
10
-
11
- ## scripts from init
12
-
13
- ```sh
14
- uv init
15
- uv run ntpy
16
- ```
17
-
18
- ## fun
19
-
20
- $$
21
- \sqrt{-1},2^{3},\sum,\pi
22
- $$
1
+ # nt25.py
2
+
3
+ Neo's Tools of Python in 2025
4
+
5
+ ## plans
6
+
7
+ - [x] fio
8
+ - [x] calc
9
+ - [x] draw
10
+ - [ ] mysql
11
+ - [ ] redis
12
+ - [ ] maptrans
13
+ - [ ] ttp
14
+
15
+ ## scripts from init
16
+
17
+ ```sh
18
+ uv init
19
+ uv run ntpy
20
+ ```
21
+
22
+ ## fun
23
+
24
+ $$
25
+ \sqrt{-1},2^{3},\sum,\pi
26
+ $$
@@ -1,9 +1,9 @@
1
1
  [project]
2
2
  name = "nt25"
3
- version = "0.1.0"
3
+ version = "0.1.2"
4
4
  description = "Neo's Tools of Python"
5
5
  readme = "README.md"
6
- requires-python = ">=3.13"
6
+ requires-python = ">=3.10"
7
7
  dependencies = [
8
8
  "matplotlib>=3.10.6",
9
9
  "openpyxl>=3.1.5",
@@ -13,7 +13,7 @@ dependencies = [
13
13
  ]
14
14
 
15
15
  [project.scripts]
16
- ntpy = "ntpy.main:main"
16
+ nt25 = "nt25.main:main"
17
17
 
18
18
  [build-system]
19
19
  requires = ["hatchling"]
@@ -1,7 +1,9 @@
1
- import importlib.metadata as meta
2
-
3
- from .lib import fio, calc, draw
4
- from .lib.draw import DType
5
-
6
- __version__ = meta.version(str(__package__))
7
- __all__ = ('__version__', 'fio', 'calc', 'draw', 'DType')
1
+ import importlib.metadata as meta
2
+
3
+ from .lib import fio, calc, draw
4
+ from .lib.draw import DType
5
+
6
+ __version__ = meta.version(str(__package__))
7
+ __samples_path__ = __file__.replace('__init__.py', 'samples')
8
+
9
+ __all__ = ('__version__', '__samples_path__', 'fio', 'calc', 'draw', 'DType')
@@ -1,104 +1,104 @@
1
- import re
2
- from typing import Iterable
3
- import numpy as np
4
-
5
- from sympy import symbols, Eq, solve
6
-
7
- from sklearn.metrics import r2_score as r2
8
- from sklearn.linear_model import LinearRegression
9
- from sklearn.preprocessing import PolynomialFeatures
10
-
11
-
12
- def str2e(s) -> str:
13
- return s if len(s) < 5 else f'{float(s):.4e}'
14
-
15
-
16
- def fl2el(fl) -> list[str]:
17
- return list(map(lambda f: str2e(str(f)), fl))
18
-
19
-
20
- def poly(x, y, degree=2) -> Iterable:
21
- return np.polyfit(x, y, degree).tolist()
22
-
23
-
24
- def polyResults(coef, x) -> Iterable:
25
- return np.poly1d(coef)(x).tolist()
26
-
27
-
28
- def polyRoots(coef) -> Iterable:
29
- return np.roots(coef).tolist()
30
-
31
-
32
- def xn2y(X, y, degree=2, output=False, foo='xn2y'):
33
- poly = PolynomialFeatures(degree=degree, include_bias=False)
34
-
35
- Xa = np.array(X)
36
- if len(Xa.shape) == 1:
37
- Xa = np.array([X])
38
-
39
- x = Xa.T
40
- xp = poly.fit_transform(x)
41
-
42
- model = LinearRegression()
43
- model.fit(xp, y)
44
- # y1 = model.predict(xp)
45
-
46
- coef = model.coef_
47
- names = poly.get_feature_names_out().tolist()
48
-
49
- eq = f'{model.intercept_:.4e} + '
50
- for i in range(len(names)):
51
- ex = names[i].replace('^', '**').replace(' ', '*')
52
- eq += f"({coef[i]:.4e})*{ex} + "
53
-
54
- eq = re.sub(r'x(\d+)', r'x[\1]', eq[:-3])
55
- func = _genFunc(foo, 'x', eq)
56
-
57
- y2 = [func(x[i]) for i in range(len(x))]
58
- yr2 = r2(y, y2)
59
-
60
- if output:
61
- q = eq.replace(' + ', ' + \\\n\t') \
62
- .replace('*x', ' * x').replace('e+00', '')
63
-
64
- print(f'{foo}: degree = {degree}, R² = {yr2:.4%}\n y = {q}\n')
65
-
66
- return {
67
- 'func': func,
68
- 'r2': yr2,
69
- 'eq': eq,
70
- }
71
-
72
-
73
- def _genFunc(name, args, expr):
74
- local = {}
75
- src = compile(f'def {name}({args}):\n\treturn {expr}', "<string>", "exec")
76
- exec(src, {}, local)
77
- return local[name]
78
-
79
-
80
- def solveEq(eq, output=False, foo='solve'):
81
- (x0, x1, y) = symbols('x:2,y')
82
- eq = re.sub(r'x\[(\d+)\]', r'x\1', eq)
83
- solution = solve(Eq(eval(eq), y), x0)
84
-
85
- real = []
86
- for s in solution:
87
- sol = str(s)
88
- if 'I' in sol:
89
- continue
90
-
91
- func = _genFunc(foo, 'y, x1=0', sol)
92
- s4e = re.sub(r'([-]?\d*\.\d+)', lambda m: str2e(m.group(0)), sol)
93
-
94
- if output:
95
- print(f'{foo}: {eq}\n x0 = {s4e}\n')
96
-
97
- real.append({
98
- 'org': eq,
99
- 'func': func,
100
- 'eq': sol,
101
- 'eq.4e': s4e,
102
- })
103
-
104
- return real
1
+ import re
2
+ from typing import Iterable
3
+ import numpy as np
4
+
5
+ from sympy import symbols, Eq, solve
6
+
7
+ from sklearn.metrics import r2_score as r2
8
+ from sklearn.linear_model import LinearRegression
9
+ from sklearn.preprocessing import PolynomialFeatures
10
+
11
+
12
+ def str2e(s) -> str:
13
+ return s if len(s) < 5 else f'{float(s):.4e}'
14
+
15
+
16
+ def fl2el(fl) -> list[str]:
17
+ return list(map(lambda f: str2e(str(f)), fl))
18
+
19
+
20
+ def poly(x, y, degree=2) -> Iterable:
21
+ return np.polyfit(x, y, degree).tolist()
22
+
23
+
24
+ def polyResults(coef, x) -> Iterable:
25
+ return np.poly1d(coef)(x).tolist()
26
+
27
+
28
+ def polyRoots(coef) -> Iterable:
29
+ return np.roots(coef).tolist()
30
+
31
+
32
+ def xn2y(X, y, degree=2, output=False, foo='xn2y'):
33
+ poly = PolynomialFeatures(degree=degree, include_bias=False)
34
+
35
+ Xa = np.array(X)
36
+ if len(Xa.shape) == 1:
37
+ Xa = np.array([X])
38
+
39
+ x = Xa.T
40
+ xp = poly.fit_transform(x)
41
+
42
+ model = LinearRegression()
43
+ model.fit(xp, y)
44
+ # y1 = model.predict(xp)
45
+
46
+ coef = model.coef_
47
+ names = poly.get_feature_names_out().tolist()
48
+
49
+ eq = f'{model.intercept_:.4e} + '
50
+ for i in range(len(names)):
51
+ ex = names[i].replace('^', '**').replace(' ', '*')
52
+ eq += f"({coef[i]:.4e})*{ex} + "
53
+
54
+ eq = re.sub(r'x(\d+)', r'x[\1]', eq[:-3])
55
+ func = _genFunc(foo, 'x', eq)
56
+
57
+ y2 = [func(x[i]) for i in range(len(x))]
58
+ yr2 = r2(y, y2)
59
+
60
+ if output:
61
+ q = eq.replace(' + ', ' + \\\n\t') \
62
+ .replace('*x', ' * x').replace('e+00', '')
63
+
64
+ print(f'{foo}: degree = {degree}, R² = {yr2:.4%}\n y = {q}\n')
65
+
66
+ return {
67
+ 'func': func,
68
+ 'r2': yr2,
69
+ 'eq': eq,
70
+ }
71
+
72
+
73
+ def _genFunc(name, args, expr):
74
+ local = {}
75
+ src = compile(f'def {name}({args}):\n\treturn {expr}', "<string>", "exec")
76
+ exec(src, {}, local)
77
+ return local[name]
78
+
79
+
80
+ def solveEq(eq, output=False, foo='solve'):
81
+ (x0, x1, y) = symbols('x:2,y')
82
+ eq = re.sub(r'x\[(\d+)\]', r'x\1', eq)
83
+ solution = solve(Eq(eval(eq), y), x0)
84
+
85
+ real = []
86
+ for s in solution:
87
+ sol = str(s)
88
+ if 'I' in sol:
89
+ continue
90
+
91
+ func = _genFunc(foo, 'y, x1=0', sol.replace('y', 'y[0]'))
92
+ s4e = re.sub(r'([-]?\d*\.\d+)', lambda m: str2e(m.group(0)), sol)
93
+
94
+ if output:
95
+ print(f'{foo}: {eq}\n x0 = {s4e}\n')
96
+
97
+ real.append({
98
+ 'org': eq,
99
+ 'func': func,
100
+ 'eq': sol,
101
+ 'eq.4e': s4e,
102
+ })
103
+
104
+ return real
@@ -0,0 +1,276 @@
1
+ from enum import Enum
2
+ from random import sample
3
+
4
+ import numpy as np
5
+
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
11
+
12
+ # import matplotlib.animation as animation
13
+
14
+
15
+ FONTS = [
16
+ 'Microsoft YaHei',
17
+ 'PingFang SC',
18
+ 'Arial Unicode MS',
19
+ 'Noto Sans CJK SC',
20
+ 'Arial'
21
+ ]
22
+
23
+ COLORS = ['blue', 'red', 'orange', 'black', 'pink']
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
50
+
51
+ if 'figure' not in ref:
52
+ fig = plot.figure()
53
+ fig.canvas.mpl_connect('close_event', onClose)
54
+
55
+ plot.rcParams['font.sans-serif'] = FONTS
56
+ plot.rcParams['axes.unicode_minus'] = False
57
+
58
+ ref['figure'] = fig
59
+ REFS.append(ref)
60
+
61
+ if 'subplot' not in ref:
62
+ ref['subplot'] = {}
63
+
64
+ fig = ref['figure']
65
+ sub = ref['subplot']
66
+
67
+ if pos not in sub:
68
+ sub[pos] = fig.add_subplot(
69
+ pos, projection='3d') if is3D else fig.add_subplot(pos)
70
+
71
+ return sub[pos]
72
+
73
+
74
+ def _genList(refer: list, length, random=False):
75
+ r = []
76
+
77
+ while len(r) < length:
78
+ r += sample(refer, len(refer)) if random else refer
79
+
80
+ return r[:length]
81
+
82
+
83
+ def _genParam(pIn, pDefault, count):
84
+ if pIn is None:
85
+ pIn = pDefault
86
+
87
+ if count == 1:
88
+ if isinstance(pIn, (list, tuple)):
89
+ pIn = pIn[0]
90
+
91
+ elif len(pIn) != count:
92
+ # print(f"bad len {len(pIn)} != {count}")
93
+ pIn = None
94
+
95
+ return pIn
96
+
97
+
98
+ def title(ref, title, pos=111, x=None, y=None, z=None):
99
+ result = False
100
+
101
+ if 'subplot' in ref:
102
+ sub = ref['subplot']
103
+
104
+ if pos in sub:
105
+ result = True
106
+ sub[pos].set_title(title)
107
+
108
+ if x:
109
+ sub[pos].set_xlabel(x)
110
+
111
+ if y:
112
+ sub[pos].set_ylabel(y)
113
+
114
+ if z:
115
+ sub[pos].set_zlabel(z)
116
+
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)
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):
133
+
134
+ if ref is None:
135
+ ref = {}
136
+
137
+ is3D = False
138
+ method = Axes.scatter
139
+
140
+ match type:
141
+ case DType.line:
142
+ method = Axes.plot
143
+
144
+ case DType.func:
145
+ method = Axes.plot
146
+
147
+ if Func is not None and min is not None and max is not None:
148
+ if callable(Func):
149
+ Func = (Func,)
150
+
151
+ X = []
152
+ Y = []
153
+
154
+ for i in range(len(Func)):
155
+ dx = np.linspace(min[i] if isinstance(min, (list, tuple)) else min,
156
+ max[i] if isinstance(max, (list, tuple)) else max)
157
+
158
+ X.append(dx)
159
+ Y.append([Func[i]([x]) for x in dx])
160
+
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
169
+
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)
254
+
255
+ return ref
256
+
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
+
271
+ def show():
272
+ plot.show()
273
+
274
+
275
+ def clear():
276
+ plot.clf()
@@ -1,116 +1,116 @@
1
- import os
2
- import csv
3
- from typing import Iterable
4
-
5
- # import openpyxl
6
- import pandas as pd
7
-
8
- ENCODINGS = ['utf-8', 'utf-8-sig', 'gbk']
9
-
10
-
11
- def _switchEnc(foo, encoding=None, *args, **kwargs):
12
- result = None
13
-
14
- if encoding is None:
15
- for enc in ENCODINGS if os.name != 'nt' else reversed(ENCODINGS):
16
- try:
17
- result = foo(encoding=enc, *args, **kwargs)
18
- break
19
- except Exception as e:
20
- print(e)
21
-
22
- else:
23
- result = foo(encoding=encoding, *args, **kwargs)
24
-
25
- return result
26
-
27
-
28
- def _getCSV(file, width, startLine, startCol, encoding):
29
- f = open(file, encoding=encoding)
30
- cf = csv.reader(f)
31
-
32
- count = 0
33
- result = [[] for _ in range(width - startCol)]
34
-
35
- for line in cf:
36
- if count >= startLine:
37
- maxWidth = len(line)
38
- for i in range(startCol, width):
39
- x = line[i].strip() if maxWidth > i else ''
40
-
41
- try:
42
- result[i - startCol].append(float(x))
43
- except ValueError:
44
- result[i - startCol].append(x)
45
-
46
- count += 1
47
-
48
- f.close()
49
- return result
50
-
51
-
52
- def _getCSV2(file, encoding=None, colsInline=True):
53
- df = pd.read_csv(file, encoding=encoding)
54
-
55
- row = df.to_numpy()
56
- r = row.T if colsInline else row
57
-
58
- return r.tolist()
59
-
60
-
61
- def getCSV(file, width=2, startLine=1, startCol=0, encoding=None):
62
- return _switchEnc(foo=_getCSV, encoding=encoding, file=file,
63
- width=width, startLine=startLine, startCol=startCol)
64
-
65
-
66
- def getCSV2(file, encoding=None):
67
- return _switchEnc(foo=_getCSV2, encoding=encoding, file=file)
68
-
69
-
70
- def saveCSV(data, file, encoding=None, colsInline=True):
71
- if encoding is None:
72
- encoding = 'utf-8'
73
-
74
- with open(file, 'w', newline='', encoding=encoding) as f:
75
- content = []
76
-
77
- for d in data:
78
- if isinstance(d, str):
79
- content.append(data[d])
80
- elif isinstance(d, Iterable):
81
- content.append(d)
82
-
83
- if colsInline:
84
- content = list(map(list, zip(*content)))
85
-
86
- cf = csv.writer(f)
87
- cf.writerows(content)
88
-
89
-
90
- def saveCSV2(data, file, encoding=None, float_format=None, colsInline=True):
91
- if data is not None:
92
- df = pd.DataFrame(data)
93
-
94
- if colsInline:
95
- df = df.T
96
-
97
- df.to_csv(file, index=False, encoding=encoding, float_format=float_format)
98
-
99
-
100
- def getXlsx(file, sheet=0, colsInLine=True):
101
- df = pd.read_excel(file, sheet_name=sheet)
102
-
103
- row = df.to_numpy()
104
- r = row.T if colsInLine else row
105
-
106
- return r.tolist()
107
-
108
-
109
- def saveXlsx(data, file, colsInline=True):
110
- if data is not None:
111
- df = pd.DataFrame(data)
112
-
113
- if colsInline:
114
- df = df.T
115
-
116
- df.to_excel(file, index=False)
1
+ import os
2
+ import csv
3
+ from typing import Iterable
4
+
5
+ # import openpyxl
6
+ import pandas as pd
7
+
8
+ ENCODINGS = ['utf-8', 'utf-8-sig', 'gbk']
9
+
10
+
11
+ def _switchEnc(foo, encoding=None, *args, **kwargs):
12
+ result = None
13
+
14
+ if encoding is None:
15
+ for enc in ENCODINGS if os.name != 'nt' else reversed(ENCODINGS):
16
+ try:
17
+ result = foo(encoding=enc, *args, **kwargs)
18
+ break
19
+ except Exception as e:
20
+ print(e)
21
+
22
+ else:
23
+ result = foo(encoding=encoding, *args, **kwargs)
24
+
25
+ return result
26
+
27
+
28
+ def _getCSV(file, width, startLine, startCol, encoding):
29
+ f = open(file, encoding=encoding)
30
+ cf = csv.reader(f)
31
+
32
+ count = 0
33
+ result = [[] for _ in range(width - startCol)]
34
+
35
+ for line in cf:
36
+ if count >= startLine:
37
+ maxWidth = len(line)
38
+ for i in range(startCol, width):
39
+ x = line[i].strip() if maxWidth > i else ''
40
+
41
+ try:
42
+ result[i - startCol].append(float(x))
43
+ except ValueError:
44
+ result[i - startCol].append(x)
45
+
46
+ count += 1
47
+
48
+ f.close()
49
+ return result
50
+
51
+
52
+ def _getCSV2(file, encoding=None, colsInline=True):
53
+ df = pd.read_csv(file, encoding=encoding)
54
+
55
+ row = df.to_numpy()
56
+ r = row.T if colsInline else row
57
+
58
+ return r.tolist()
59
+
60
+
61
+ def getCSV(file, width=2, startLine=1, startCol=0, encoding=None):
62
+ return _switchEnc(foo=_getCSV, encoding=encoding, file=file,
63
+ width=width, startLine=startLine, startCol=startCol)
64
+
65
+
66
+ def getCSV2(file, encoding=None):
67
+ return _switchEnc(foo=_getCSV2, encoding=encoding, file=file)
68
+
69
+
70
+ def saveCSV(data, file, encoding=None, colsInline=True):
71
+ if encoding is None:
72
+ encoding = 'utf-8'
73
+
74
+ with open(file, 'w', newline='', encoding=encoding) as f:
75
+ content = []
76
+
77
+ for d in data:
78
+ if isinstance(d, str):
79
+ content.append(data[d])
80
+ elif isinstance(d, Iterable):
81
+ content.append(d)
82
+
83
+ if colsInline:
84
+ content = list(map(list, zip(*content)))
85
+
86
+ cf = csv.writer(f)
87
+ cf.writerows(content)
88
+
89
+
90
+ def saveCSV2(data, file, encoding=None, float_format=None, colsInline=True):
91
+ if data is not None:
92
+ df = pd.DataFrame(data)
93
+
94
+ if colsInline:
95
+ df = df.T
96
+
97
+ df.to_csv(file, index=False, encoding=encoding, float_format=float_format)
98
+
99
+
100
+ def getXlsx(file, sheet=0, colsInLine=True):
101
+ df = pd.read_excel(file, sheet_name=sheet)
102
+
103
+ row = df.to_numpy()
104
+ r = row.T if colsInLine else row
105
+
106
+ return r.tolist()
107
+
108
+
109
+ def saveXlsx(data, file, colsInline=True):
110
+ if data is not None:
111
+ df = pd.DataFrame(data)
112
+
113
+ if colsInline:
114
+ df = df.T
115
+
116
+ df.to_excel(file, index=False)
@@ -0,0 +1,74 @@
1
+ from nt25 import fio, calc, draw, DType, __version__, __samples_path__
2
+
3
+ # import timeit
4
+ # timeit.timeit('', number=100, globals=globals())
5
+
6
+
7
+ def main():
8
+ print(f"Hello from {__package__}({__version__})! ")
9
+
10
+ # [Neo] some file I/O: csv, xlsx
11
+ fio.saveCSV({
12
+ 'Name': ['Alice', 'Bob', 'Charlie'],
13
+ 'Age': [25.2, 30, 35],
14
+ 'City': ['New York', 'Los Angeles', 'Chicago']
15
+ }, "out.csv", colsInline=False)
16
+
17
+ data = fio.getXlsx(__samples_path__ + '/test.xlsx')
18
+ fio.saveCSV(data, "out2.csv")
19
+
20
+ h = data[0]
21
+ s = data[1]
22
+ v = data[2]
23
+
24
+ # [Neo] some poly calculates
25
+ c = calc.poly(h, v)
26
+ ce = calc.fl2el(c)
27
+ print(c, ce)
28
+
29
+ foo = calc.xn2y(h, v, degree=3, output=True)
30
+ bar = calc.solveEq(foo['eq'], output=False)
31
+
32
+ func = foo['func']
33
+ bfunc = bar[0]['func']
34
+
35
+ Y = range(1000, 2000, 200)
36
+ X = [bfunc([y]) for y in Y]
37
+
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)
42
+ draw.show()
43
+
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
67
+ bar = calc.solveEq(foo['eq'], output=True)
68
+
69
+ if len(bar) > 0:
70
+ print('s> 750, 1.5 ~', bar[0]['func'](y=[750], x1=1.5))
71
+
72
+
73
+ if __name__ == "__main__":
74
+ main()
@@ -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,141 +0,0 @@
1
- from enum import Enum
2
- from random import sample
3
-
4
- import numpy as np
5
-
6
- from matplotlib.axes import Axes
7
- from matplotlib import pyplot as plot
8
-
9
- # import matplotlib.animation as animation
10
-
11
-
12
- FONTS = ['PingFang SC', 'Microsoft YaHei', 'Arial']
13
- COLORS = ['blue', 'red', 'orange', 'black', 'pink']
14
-
15
-
16
- def _getPlot(ref, pos, font='Roboto') -> Axes:
17
- 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']
21
- plot.rcParams['axes.unicode_minus'] = False
22
-
23
- if 'subplot' not in ref:
24
- ref['subplot'] = {}
25
-
26
- fig = ref['figure']
27
- sub = ref['subplot']
28
-
29
- if pos not in sub:
30
- sub[pos] = fig.add_subplot(pos)
31
-
32
- return sub[pos]
33
-
34
-
35
- def _genList(refer: list, length, random=False):
36
- r = []
37
-
38
- while len(r) < length:
39
- r += sample(refer, len(refer)) if random else refer
40
-
41
- return r[:length]
42
-
43
-
44
- def _coord(ref, X, Y, color, pos, randomColor, method, *args, **kwargs):
45
- Xa = np.array(X)
46
- Ya = np.array(Y)
47
-
48
- if Xa.shape != Ya.shape:
49
- print(f"bad shape {Xa.shape} != {Ya.shape}")
50
- return
51
-
52
- count = 1
53
- # count = Xa.shape[0] if len(Xa.shape) > 1 else 1
54
-
55
- if len(Xa.shape) > 1:
56
- count = Xa.shape[0]
57
- if count == 1:
58
- X = X[0]
59
- Y = Y[0]
60
-
61
- if color is None:
62
- color = _genList(COLORS, count, random=randomColor)
63
-
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
70
-
71
- if pos is None:
72
- pos = [111] * count
73
-
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
80
-
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)
88
-
89
- return ref
90
-
91
-
92
- class DType(Enum):
93
- scatter = 1,
94
- line = 2,
95
- func = 3,
96
-
97
-
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
- if ref is None:
102
- ref = {}
103
-
104
- match type:
105
- case DType.scatter:
106
- func = Axes.scatter
107
-
108
- case DType.line:
109
- func = Axes.plot
110
-
111
- case DType.func:
112
- func = Axes.plot
113
- if Func is not None and min is not None and max is not None:
114
- if callable(Func):
115
- Func = (Func,)
116
-
117
- X = []
118
- Y = []
119
-
120
- for i in range(len(Func)):
121
- dx = np.linspace(min[i] if isinstance(min, (list, tuple)) else min,
122
- max[i] if isinstance(max, (list, tuple)) else max)
123
-
124
- X.append(dx)
125
- Y.append([Func[i]([x]) for x in dx])
126
-
127
- ref = _coord(ref, X, Y, color=color, pos=pos, randomColor=randomColor,
128
- method=func, *args, **kwargs)
129
-
130
- if show:
131
- plot.show()
132
-
133
- return ref
134
-
135
-
136
- def show():
137
- plot.show()
138
-
139
-
140
- def clear():
141
- plot.clf()
@@ -1,54 +0,0 @@
1
- from ntpy import fio, calc, draw, DType, __version__
2
-
3
- # import timeit
4
- # timeit.timeit('', number=100, globals=globals())
5
-
6
-
7
- def main():
8
- print(f"Hello from {__package__}({__version__})! ")
9
-
10
- # [Neo] some file I/O: csv, xlsx
11
- fio.saveCSV({
12
- 'Name': ['Alice', 'Bob', 'Charlie'],
13
- 'Age': [25.2, 30, 35],
14
- 'City': ['New York', 'Los Angeles', 'Chicago']
15
- }, "out.csv", colsInline=False)
16
-
17
- data = fio.getXlsx('ds/qs.xlsx')
18
- fio.saveCSV(data, "out2.csv")
19
-
20
- h = data[0]
21
- s = data[1]
22
- v = data[2]
23
-
24
- # [Neo] some poly calculates
25
- c = calc.poly(h, v)
26
- ce = calc.fl2el(c)
27
- print(c, ce)
28
-
29
- foo = calc.xn2y(h, v, degree=3, output=True)
30
- bar = calc.solveEq(foo['eq'])
31
-
32
- func = foo['func']
33
- bfunc = bar[0]['func']
34
-
35
- Y = range(1000, 2000, 200)
36
- X = [bfunc(y) for y in Y]
37
-
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')
43
- draw.show()
44
-
45
- # [Neo] and 3d calcs
46
- foo = calc.xn2y([h, s], v, degree=3, output=False)
47
- bar = calc.solveEq(foo['eq'], output=True)
48
-
49
- if len(bar) > 0:
50
- print('s> 750, 1.5 ~', bar[0]['func'](y=750, x1=1.5))
51
-
52
-
53
- if __name__ == "__main__":
54
- main()
File without changes