nt25 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.
nt25/__init__.py ADDED
@@ -0,0 +1,7 @@
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')
nt25/lib/calc.py ADDED
@@ -0,0 +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
nt25/lib/draw.py ADDED
@@ -0,0 +1,141 @@
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()
nt25/lib/fio.py ADDED
@@ -0,0 +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)
nt25/main.py ADDED
@@ -0,0 +1,54 @@
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()
@@ -0,0 +1,34 @@
1
+ Metadata-Version: 2.4
2
+ Name: nt25
3
+ Version: 0.1.0
4
+ Summary: Neo's Tools of Python
5
+ Requires-Python: >=3.13
6
+ Requires-Dist: matplotlib>=3.10.6
7
+ Requires-Dist: openpyxl>=3.1.5
8
+ Requires-Dist: pandas>=2.3.2
9
+ Requires-Dist: scikit-learn>=1.7.1
10
+ Requires-Dist: sympy>=1.14.0
11
+ Description-Content-Type: text/markdown
12
+
13
+ # NT.py
14
+
15
+ Neo's Tools of Python
16
+
17
+ ## plans
18
+
19
+ - [x] fio
20
+ - [x] calc
21
+ - [ ] draw with 3d
22
+
23
+ ## scripts from init
24
+
25
+ ```sh
26
+ uv init
27
+ uv run ntpy
28
+ ```
29
+
30
+ ## fun
31
+
32
+ $$
33
+ \sqrt{-1},2^{3},\sum,\pi
34
+ $$
@@ -0,0 +1,9 @@
1
+ nt25/__init__.py,sha256=VB6BTxQeAy3eAqEzpe2x0Kc4w-TGakvtZPYzBPq8ldY,207
2
+ nt25/main.py,sha256=Zf0bOV3YciAb8kTbljR3C9wEspUJ4jcexjTEXeiP5vU,1256
3
+ nt25/lib/calc.py,sha256=HHjp9bIEszLloB1TurnMSNqk0yo6Jyd7egMEeoQIK3o,2346
4
+ nt25/lib/draw.py,sha256=HY6O1r-NQmue24gG5WHTocq4gDPpM-qconoy-Ozfs7g,3161
5
+ nt25/lib/fio.py,sha256=ujt4AbNUX6RyjHwqUn2AXly9ZWjgslzhqdY2DK7Q4Lo,2641
6
+ nt25-0.1.0.dist-info/METADATA,sha256=oGVEI_Ewpob8YuIfvyMM9uUE3PDRXZaQl9yvXRVKSBI,477
7
+ nt25-0.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
8
+ nt25-0.1.0.dist-info/entry_points.txt,sha256=jymrdQKvCJUGsJFD51GtyJ0AEBAzpiXagA6NVwYuUmw,40
9
+ nt25-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.27.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ ntpy = ntpy.main:main