flkit 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.
- flkit/__init__.py +2 -0
- flkit/alg/__init__.py +68 -0
- flkit/alg/build_idx.py +9 -0
- flkit/alg/c_track.py +88 -0
- flkit/alg/collierydb.py +1217 -0
- flkit/alg/del2.py +421 -0
- flkit/alg/delaunay_triangulation.py +476 -0
- flkit/alg/finite_plane_distance.py +239 -0
- flkit/alg/get_up_low.py +32 -0
- flkit/alg/in_tin.py +139 -0
- flkit/alg/index.py +9 -0
- flkit/alg/inter/BasePredictor.py +69 -0
- flkit/alg/inter/Kriging.py +226 -0
- flkit/alg/inter/KrigingM.py +262 -0
- flkit/alg/inter/LossFuncs.py +164 -0
- flkit/alg/inter/__init__.py +178 -0
- flkit/alg/inter/idw.py +253 -0
- flkit/alg/inter/midw.py +145 -0
- flkit/alg/inter/nearest_neighbor.py +445 -0
- flkit/alg/inter/rbf.py +345 -0
- flkit/alg/inter/trilinear.py +572 -0
- flkit/alg/point_in_polygon.py +126 -0
- flkit/alg/point_in_volume.py +188 -0
- flkit/alg/point_in_volume_rs.pyi +7 -0
- flkit/alg/point_to_triangle.py +116 -0
- flkit/alg/point_to_triangle_mesh.py +309 -0
- flkit/alg/point_to_triangle_rs.pyi +9 -0
- flkit/alg/rotated_rect.py +184 -0
- flkit/db/__init__.py +17 -0
- flkit/db/db_model.py +724 -0
- flkit/db/duck_model.py +151 -0
- flkit/db/fileobj.py +72 -0
- flkit/db/path_utl.py +174 -0
- flkit/mtcli/__init__.py +18 -0
- flkit/mtcli/core.py +489 -0
- flkit/mtcli/parse.py +218 -0
- flkit/py.typed +0 -0
- flkit/tools/__init__.py +28 -0
- flkit/tools/del_key.py +13 -0
- flkit/tools/dict_to_list.py +10 -0
- flkit/tools/get_region.py +42 -0
- flkit/tools/max_key.py +7 -0
- flkit/tools/mongo.py +119 -0
- flkit/tools/mt_dash.py +121 -0
- flkit/tools/prase_type.py +27 -0
- flkit/typr/Res.py +21 -0
- flkit/typr/__init__.py +107 -0
- flkit/typr/c_grid.py +425 -0
- flkit/typr/console.py +283 -0
- flkit/typr/engine.py +59 -0
- flkit/typr/getenv.py +89 -0
- flkit/typr/result.py +81 -0
- flkit/typr/table.py +34 -0
- flkit/typr/utils.py +542 -0
- flkit/typr/verify.py +64 -0
- flkit/typr/webview.py +219 -0
- flkit/typr/wstask.py +344 -0
- flkit-0.1.0.dist-info/METADATA +186 -0
- flkit-0.1.0.dist-info/RECORD +60 -0
- flkit-0.1.0.dist-info/WHEEL +4 -0
flkit/alg/inter/idw.py
ADDED
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
反距离权重插值算法实现
|
|
5
|
+
Inverse Distance Weighting (IDW) Interpolation
|
|
6
|
+
|
|
7
|
+
IDW是一种基于距离的插值方法,距离越近的点权重越大。
|
|
8
|
+
适用于地理空间数据插值,计算简单高效。
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import numpy as np
|
|
12
|
+
from scipy.spatial import cKDTree
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class IDW2D:
|
|
16
|
+
"""
|
|
17
|
+
二维反距离加权插值
|
|
18
|
+
|
|
19
|
+
适用于地形高程插值、温度分布等二维空间数据插值
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
def __init__(self, p: float = 2.0, k: int = 12, eps: float = 1e-8):
|
|
23
|
+
"""
|
|
24
|
+
初始化IDW2D插值器
|
|
25
|
+
|
|
26
|
+
Parameters:
|
|
27
|
+
-----------
|
|
28
|
+
p : float, default=2.0
|
|
29
|
+
距离权重指数,值越大距离影响越强
|
|
30
|
+
k : int, default=12
|
|
31
|
+
使用的最近邻点数量
|
|
32
|
+
eps : float, default=1e-8
|
|
33
|
+
数值稳定性参数
|
|
34
|
+
"""
|
|
35
|
+
self.p = p
|
|
36
|
+
self.k = k
|
|
37
|
+
self.eps = eps
|
|
38
|
+
self.tree = None
|
|
39
|
+
self.known_z = None
|
|
40
|
+
|
|
41
|
+
def fit(self, xyzv: np.ndarray):
|
|
42
|
+
"""
|
|
43
|
+
训练IDW模型
|
|
44
|
+
|
|
45
|
+
Parameters:
|
|
46
|
+
-----------
|
|
47
|
+
xyzv : np.ndarray, shape (N, 3)
|
|
48
|
+
已知点数据,每行为 [x, y, z],其中z为插值目标值
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
--------
|
|
52
|
+
self : IDW2D
|
|
53
|
+
返回自身以支持链式调用
|
|
54
|
+
"""
|
|
55
|
+
xyzv = np.atleast_2d(xyzv)
|
|
56
|
+
if xyzv.shape[1] != 3:
|
|
57
|
+
raise ValueError("输入数据必须是3列:[x, y, z]")
|
|
58
|
+
|
|
59
|
+
self.tree = cKDTree(xyzv[:, :2])
|
|
60
|
+
self.known_z = xyzv[:, 2]
|
|
61
|
+
return self
|
|
62
|
+
|
|
63
|
+
def predict(self, xy: np.ndarray):
|
|
64
|
+
"""
|
|
65
|
+
在指定位置进行插值预测
|
|
66
|
+
|
|
67
|
+
Parameters:
|
|
68
|
+
-----------
|
|
69
|
+
xy : np.ndarray, shape (M, 2) or (2,)
|
|
70
|
+
待插值点的坐标 [x, y]
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
--------
|
|
74
|
+
float or np.ndarray
|
|
75
|
+
- 单点输入 (2,): 返回标量值
|
|
76
|
+
- 多点输入 (M, 2): 返回数组 shape (M,)
|
|
77
|
+
"""
|
|
78
|
+
if self.tree is None:
|
|
79
|
+
raise ValueError("模型尚未训练,请先调用 fit() 方法")
|
|
80
|
+
|
|
81
|
+
# 检查输入是单点还是多点
|
|
82
|
+
is_single_point = xy.ndim == 1 or (xy.ndim == 2 and xy.shape[0] == 1)
|
|
83
|
+
|
|
84
|
+
xy = np.atleast_2d(xy)
|
|
85
|
+
if xy.shape[1] != 2:
|
|
86
|
+
raise ValueError("预测点坐标必须是2列:[x, y]")
|
|
87
|
+
|
|
88
|
+
# 查找最近邻点
|
|
89
|
+
dist, idx = self.tree.query(xy, k=min(self.k, len(self.known_z)), eps=self.eps)
|
|
90
|
+
|
|
91
|
+
# 处理单点查询的情况
|
|
92
|
+
if dist.ndim == 1:
|
|
93
|
+
dist = dist.reshape(1, -1)
|
|
94
|
+
idx = idx.reshape(1, -1)
|
|
95
|
+
|
|
96
|
+
# 避免除零错误
|
|
97
|
+
dist = np.maximum(dist, self.eps)
|
|
98
|
+
|
|
99
|
+
# 计算权重
|
|
100
|
+
w = 1.0 / (dist**self.p)
|
|
101
|
+
|
|
102
|
+
# 加权平均
|
|
103
|
+
z = np.sum(w * self.known_z[idx], axis=1) / np.sum(w, axis=1)
|
|
104
|
+
|
|
105
|
+
# 根据输入类型返回相应格式
|
|
106
|
+
if is_single_point:
|
|
107
|
+
return float(z[0]) # 单点返回标量
|
|
108
|
+
else:
|
|
109
|
+
return z # 多点返回数组
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class IDW3D:
|
|
113
|
+
"""
|
|
114
|
+
三维反距离加权插值
|
|
115
|
+
|
|
116
|
+
适用于三维空间中的属性插值,如地质属性、污染物浓度等
|
|
117
|
+
"""
|
|
118
|
+
|
|
119
|
+
def __init__(self, p: float = 2.0, k: int = 15, eps: float = 1e-8):
|
|
120
|
+
"""
|
|
121
|
+
初始化IDW3D插值器
|
|
122
|
+
|
|
123
|
+
Parameters:
|
|
124
|
+
-----------
|
|
125
|
+
p : float, default=2.0
|
|
126
|
+
距离权重指数
|
|
127
|
+
k : int, default=15
|
|
128
|
+
使用的最近邻点数量
|
|
129
|
+
eps : float, default=1e-8
|
|
130
|
+
数值稳定性参数
|
|
131
|
+
"""
|
|
132
|
+
self.p = p
|
|
133
|
+
self.k = k
|
|
134
|
+
self.eps = eps
|
|
135
|
+
self.tree = None
|
|
136
|
+
self.known_v = None
|
|
137
|
+
|
|
138
|
+
def fit(self, xyzv: np.ndarray):
|
|
139
|
+
"""
|
|
140
|
+
训练IDW3D模型
|
|
141
|
+
|
|
142
|
+
Parameters:
|
|
143
|
+
-----------
|
|
144
|
+
xyzv : np.ndarray, shape (N, 4)
|
|
145
|
+
已知点数据,每行为 [x, y, z, value]
|
|
146
|
+
|
|
147
|
+
Returns:
|
|
148
|
+
--------
|
|
149
|
+
self : IDW3D
|
|
150
|
+
返回自身以支持链式调用
|
|
151
|
+
"""
|
|
152
|
+
xyzv = np.atleast_2d(xyzv)
|
|
153
|
+
if xyzv.shape[1] != 4:
|
|
154
|
+
raise ValueError("输入数据必须是4列:[x, y, z, value]")
|
|
155
|
+
|
|
156
|
+
self.tree = cKDTree(xyzv[:, :3])
|
|
157
|
+
self.known_v = xyzv[:, 3]
|
|
158
|
+
return self
|
|
159
|
+
|
|
160
|
+
def predict(self, xyz: np.ndarray):
|
|
161
|
+
"""
|
|
162
|
+
在指定位置进行插值预测
|
|
163
|
+
|
|
164
|
+
Parameters:
|
|
165
|
+
-----------
|
|
166
|
+
xyz : np.ndarray, shape (M, 3) or (3,)
|
|
167
|
+
待插值点的坐标 [x, y, z]
|
|
168
|
+
|
|
169
|
+
Returns:
|
|
170
|
+
--------
|
|
171
|
+
float or np.ndarray
|
|
172
|
+
- 单点输入 (3,): 返回标量值
|
|
173
|
+
- 多点输入 (M, 3): 返回数组 shape (M,)
|
|
174
|
+
"""
|
|
175
|
+
if self.tree is None:
|
|
176
|
+
raise ValueError("模型尚未训练,请先调用 fit() 方法")
|
|
177
|
+
|
|
178
|
+
# 检查输入是单点还是多点
|
|
179
|
+
is_single_point = xyz.ndim == 1 or (xyz.ndim == 2 and xyz.shape[0] == 1)
|
|
180
|
+
|
|
181
|
+
xyz = np.atleast_2d(xyz)
|
|
182
|
+
if xyz.shape[1] != 3:
|
|
183
|
+
raise ValueError("预测点坐标必须是3列:[x, y, z]")
|
|
184
|
+
|
|
185
|
+
# 查找最近邻点
|
|
186
|
+
dist, idx = self.tree.query(xyz, k=min(self.k, len(self.known_v)), eps=self.eps)
|
|
187
|
+
|
|
188
|
+
# 处理单点查询的情况
|
|
189
|
+
if dist.ndim == 1:
|
|
190
|
+
dist = dist.reshape(1, -1)
|
|
191
|
+
idx = idx.reshape(1, -1)
|
|
192
|
+
|
|
193
|
+
# 避免除零错误
|
|
194
|
+
dist = np.maximum(dist, self.eps)
|
|
195
|
+
|
|
196
|
+
# 计算权重
|
|
197
|
+
w = 1.0 / (dist**self.p)
|
|
198
|
+
|
|
199
|
+
# 加权平均
|
|
200
|
+
v = np.sum(w * self.known_v[idx], axis=1) / np.sum(w, axis=1)
|
|
201
|
+
|
|
202
|
+
# 根据输入类型返回相应格式
|
|
203
|
+
if is_single_point:
|
|
204
|
+
return float(v[0]) # 单点返回标量
|
|
205
|
+
else:
|
|
206
|
+
return v # 多点返回数组
|
|
207
|
+
|
|
208
|
+
def predict_grid(self, x_range, y_range, z_range, resolution=None):
|
|
209
|
+
"""
|
|
210
|
+
在规则网格上进行预测
|
|
211
|
+
|
|
212
|
+
Parameters:
|
|
213
|
+
-----------
|
|
214
|
+
x_range : tuple
|
|
215
|
+
x方向的范围 (x_min, x_max)
|
|
216
|
+
y_range : tuple
|
|
217
|
+
y方向的范围 (y_min, y_max)
|
|
218
|
+
z_range : tuple
|
|
219
|
+
z方向的范围 (z_min, z_max)
|
|
220
|
+
resolution : tuple, optional
|
|
221
|
+
网格分辨率 (nx, ny, nz),默认为 (50, 50, 50)
|
|
222
|
+
|
|
223
|
+
Returns:
|
|
224
|
+
--------
|
|
225
|
+
tuple
|
|
226
|
+
(grid_x, grid_y, grid_z, predictions)
|
|
227
|
+
- grid_x, grid_y, grid_z: 网格坐标
|
|
228
|
+
- predictions: 预测值网格
|
|
229
|
+
"""
|
|
230
|
+
if self.tree is None:
|
|
231
|
+
raise ValueError("模型尚未训练,请先调用 fit() 方法")
|
|
232
|
+
|
|
233
|
+
if resolution is None:
|
|
234
|
+
resolution = (50, 50, 50)
|
|
235
|
+
|
|
236
|
+
# 创建网格
|
|
237
|
+
x = np.linspace(x_range[0], x_range[1], resolution[0])
|
|
238
|
+
y = np.linspace(y_range[0], y_range[1], resolution[1])
|
|
239
|
+
z = np.linspace(z_range[0], z_range[1], resolution[2])
|
|
240
|
+
|
|
241
|
+
grid_x, grid_y, grid_z = np.meshgrid(x, y, z, indexing="ij")
|
|
242
|
+
|
|
243
|
+
# 展平网格点进行预测
|
|
244
|
+
points = np.column_stack([grid_x.ravel(), grid_y.ravel(), grid_z.ravel()])
|
|
245
|
+
|
|
246
|
+
predictions = self.predict(points)
|
|
247
|
+
predictions = predictions.reshape(grid_x.shape)
|
|
248
|
+
|
|
249
|
+
return grid_x, grid_y, grid_z, predictions
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
# 向下兼容旧接口
|
|
253
|
+
IDW = IDW2D
|
flkit/alg/inter/midw.py
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from .BasePredictor import Predictor
|
|
3
|
+
from .LossFuncs import ErrorMetrics
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class IDW(Predictor):
|
|
7
|
+
class IDWModel:
|
|
8
|
+
def __init__(self, x, y, value, power=2):
|
|
9
|
+
self.x = x
|
|
10
|
+
self.y = y
|
|
11
|
+
self.value = value
|
|
12
|
+
self.power = power
|
|
13
|
+
|
|
14
|
+
def execute(self, point_x, point_y):
|
|
15
|
+
numerator = 0
|
|
16
|
+
denominator = 0
|
|
17
|
+
|
|
18
|
+
for i, (x, y, val) in enumerate(zip(self.x, self.y, self.value)):
|
|
19
|
+
d = ((x - point_x) ** 2 + (y - point_y) ** 2) ** 0.5
|
|
20
|
+
if d == 0:
|
|
21
|
+
return val, 0
|
|
22
|
+
weight = 1 / (d**self.power)
|
|
23
|
+
numerator += weight * val
|
|
24
|
+
denominator += weight
|
|
25
|
+
|
|
26
|
+
result = numerator / denominator
|
|
27
|
+
return result, 0
|
|
28
|
+
|
|
29
|
+
def fit(self, data: np.ndarray):
|
|
30
|
+
x = data[:, 0]
|
|
31
|
+
y = data[:, 1]
|
|
32
|
+
z = data[:, 2]
|
|
33
|
+
self.model = self.IDWModel(x, y, z)
|
|
34
|
+
|
|
35
|
+
def predict(self, points: np.ndarray):
|
|
36
|
+
z1 = np.zeros(points.shape[0])
|
|
37
|
+
for i in range(points.shape[0]):
|
|
38
|
+
z1[i], _ = self.model.execute(points[i, 0], points[i, 1])
|
|
39
|
+
return z1
|
|
40
|
+
|
|
41
|
+
def loss(self, data, res):
|
|
42
|
+
return ErrorMetrics.mse(data, res)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class IDWOpm(Predictor):
|
|
46
|
+
class IDWModel:
|
|
47
|
+
def __init__(self, x, y, value, power=2):
|
|
48
|
+
self.x = x
|
|
49
|
+
self.y = y
|
|
50
|
+
self.value = value
|
|
51
|
+
self.power = power
|
|
52
|
+
|
|
53
|
+
def execute(self, point_x, point_y):
|
|
54
|
+
numerator = 0
|
|
55
|
+
denominator = 0
|
|
56
|
+
|
|
57
|
+
for i, (x, y, val) in enumerate(zip(self.x, self.y, self.value)):
|
|
58
|
+
d = ((x - point_x) ** 2 + (y - point_y) ** 2) ** 0.5
|
|
59
|
+
if d == 0:
|
|
60
|
+
return val, 0
|
|
61
|
+
weight = 1 / (d**self.power)
|
|
62
|
+
numerator += weight * val
|
|
63
|
+
denominator += weight
|
|
64
|
+
|
|
65
|
+
result = numerator / denominator
|
|
66
|
+
return result, 0
|
|
67
|
+
|
|
68
|
+
def fit(self, data):
|
|
69
|
+
arr = np.asarray(data)
|
|
70
|
+
if arr.ndim != 2 or arr.shape[1] != 3:
|
|
71
|
+
raise ValueError("输入数据必须是3列:[x, y, z]")
|
|
72
|
+
x, y, z = arr[:, 0], arr[:, 1], arr[:, 2]
|
|
73
|
+
self.model = self.IDWModel(x.tolist(), y.tolist(), z.tolist())
|
|
74
|
+
return self
|
|
75
|
+
|
|
76
|
+
def predict(self, points):
|
|
77
|
+
arr = np.asarray(points)
|
|
78
|
+
if arr.ndim == 1:
|
|
79
|
+
x, y = float(arr[0]), float(arr[1])
|
|
80
|
+
result, _ = self.model.execute(x, y)
|
|
81
|
+
return result
|
|
82
|
+
elif arr.ndim == 2 and arr.shape[1] == 2:
|
|
83
|
+
z1 = np.zeros(arr.shape[0], dtype=float)
|
|
84
|
+
for i in range(arr.shape[0]):
|
|
85
|
+
z1[i], _ = self.model.execute(float(arr[i, 0]), float(arr[i, 1]))
|
|
86
|
+
return z1
|
|
87
|
+
else:
|
|
88
|
+
raise ValueError("预测点坐标必须是2列:[x, y] 或形状 (M, 2)")
|
|
89
|
+
|
|
90
|
+
def loss(self, data, res):
|
|
91
|
+
return ErrorMetrics.mse(data, res)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class IDWOpm3D(Predictor):
|
|
95
|
+
class IDWModel:
|
|
96
|
+
def __init__(self, x, y, z, value, power=2):
|
|
97
|
+
self.x = x
|
|
98
|
+
self.y = y
|
|
99
|
+
self.z = z
|
|
100
|
+
self.value = value
|
|
101
|
+
self.power = power
|
|
102
|
+
|
|
103
|
+
def execute(self, point_x, point_y, point_z):
|
|
104
|
+
numerator = 0
|
|
105
|
+
denominator = 0
|
|
106
|
+
|
|
107
|
+
for i, (x, y, z, val) in enumerate(zip(self.x, self.y, self.z, self.value)):
|
|
108
|
+
d = (
|
|
109
|
+
(x - point_x) ** 2 + (y - point_y) ** 2 + (z - point_z) ** 2
|
|
110
|
+
) ** 0.5
|
|
111
|
+
if d == 0:
|
|
112
|
+
return val, 0
|
|
113
|
+
weight = 1 / (d**self.power)
|
|
114
|
+
numerator += weight * val
|
|
115
|
+
denominator += weight
|
|
116
|
+
|
|
117
|
+
result = numerator / denominator
|
|
118
|
+
return result, 0
|
|
119
|
+
|
|
120
|
+
def fit(self, data):
|
|
121
|
+
arr = np.asarray(data)
|
|
122
|
+
if arr.ndim != 2 or arr.shape[1] != 4:
|
|
123
|
+
raise ValueError("输入数据必须是4列:[x, y, z, value]")
|
|
124
|
+
x, y, z, value = arr[:, 0], arr[:, 1], arr[:, 2], arr[:, 3]
|
|
125
|
+
self.model = self.IDWModel(x.tolist(), y.tolist(), z.tolist(), value.tolist())
|
|
126
|
+
return self
|
|
127
|
+
|
|
128
|
+
def predict(self, points):
|
|
129
|
+
arr = np.asarray(points)
|
|
130
|
+
if arr.ndim == 1:
|
|
131
|
+
x, y, z = float(arr[0]), float(arr[1]), float(arr[2])
|
|
132
|
+
result, _ = self.model.execute(x, y, z)
|
|
133
|
+
return result
|
|
134
|
+
elif arr.ndim == 2 and arr.shape[1] == 3:
|
|
135
|
+
z1 = np.zeros(arr.shape[0], dtype=float)
|
|
136
|
+
for i in range(arr.shape[0]):
|
|
137
|
+
z1[i], _ = self.model.execute(
|
|
138
|
+
float(arr[i, 0]), float(arr[i, 1]), float(arr[i, 2])
|
|
139
|
+
)
|
|
140
|
+
return z1
|
|
141
|
+
else:
|
|
142
|
+
raise ValueError("预测点坐标必须是3列:[x, y, z] 或形状 (M, 3)")
|
|
143
|
+
|
|
144
|
+
def loss(self, data, res):
|
|
145
|
+
return ErrorMetrics.mse(data, res)
|