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.
Files changed (60) hide show
  1. flkit/__init__.py +2 -0
  2. flkit/alg/__init__.py +68 -0
  3. flkit/alg/build_idx.py +9 -0
  4. flkit/alg/c_track.py +88 -0
  5. flkit/alg/collierydb.py +1217 -0
  6. flkit/alg/del2.py +421 -0
  7. flkit/alg/delaunay_triangulation.py +476 -0
  8. flkit/alg/finite_plane_distance.py +239 -0
  9. flkit/alg/get_up_low.py +32 -0
  10. flkit/alg/in_tin.py +139 -0
  11. flkit/alg/index.py +9 -0
  12. flkit/alg/inter/BasePredictor.py +69 -0
  13. flkit/alg/inter/Kriging.py +226 -0
  14. flkit/alg/inter/KrigingM.py +262 -0
  15. flkit/alg/inter/LossFuncs.py +164 -0
  16. flkit/alg/inter/__init__.py +178 -0
  17. flkit/alg/inter/idw.py +253 -0
  18. flkit/alg/inter/midw.py +145 -0
  19. flkit/alg/inter/nearest_neighbor.py +445 -0
  20. flkit/alg/inter/rbf.py +345 -0
  21. flkit/alg/inter/trilinear.py +572 -0
  22. flkit/alg/point_in_polygon.py +126 -0
  23. flkit/alg/point_in_volume.py +188 -0
  24. flkit/alg/point_in_volume_rs.pyi +7 -0
  25. flkit/alg/point_to_triangle.py +116 -0
  26. flkit/alg/point_to_triangle_mesh.py +309 -0
  27. flkit/alg/point_to_triangle_rs.pyi +9 -0
  28. flkit/alg/rotated_rect.py +184 -0
  29. flkit/db/__init__.py +17 -0
  30. flkit/db/db_model.py +724 -0
  31. flkit/db/duck_model.py +151 -0
  32. flkit/db/fileobj.py +72 -0
  33. flkit/db/path_utl.py +174 -0
  34. flkit/mtcli/__init__.py +18 -0
  35. flkit/mtcli/core.py +489 -0
  36. flkit/mtcli/parse.py +218 -0
  37. flkit/py.typed +0 -0
  38. flkit/tools/__init__.py +28 -0
  39. flkit/tools/del_key.py +13 -0
  40. flkit/tools/dict_to_list.py +10 -0
  41. flkit/tools/get_region.py +42 -0
  42. flkit/tools/max_key.py +7 -0
  43. flkit/tools/mongo.py +119 -0
  44. flkit/tools/mt_dash.py +121 -0
  45. flkit/tools/prase_type.py +27 -0
  46. flkit/typr/Res.py +21 -0
  47. flkit/typr/__init__.py +107 -0
  48. flkit/typr/c_grid.py +425 -0
  49. flkit/typr/console.py +283 -0
  50. flkit/typr/engine.py +59 -0
  51. flkit/typr/getenv.py +89 -0
  52. flkit/typr/result.py +81 -0
  53. flkit/typr/table.py +34 -0
  54. flkit/typr/utils.py +542 -0
  55. flkit/typr/verify.py +64 -0
  56. flkit/typr/webview.py +219 -0
  57. flkit/typr/wstask.py +344 -0
  58. flkit-0.1.0.dist-info/METADATA +186 -0
  59. flkit-0.1.0.dist-info/RECORD +60 -0
  60. flkit-0.1.0.dist-info/WHEEL +4 -0
@@ -0,0 +1,445 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ 最近邻插值算法实现
5
+ Nearest Neighbor Interpolation
6
+
7
+ 最近邻插值是最简单的插值方法,将查询点的值设为最近已知点的值。
8
+ 适用于分类数据或需要保持原始值的场景。
9
+ """
10
+
11
+ import numpy as np
12
+ from scipy.spatial import cKDTree
13
+ from sklearn.neighbors import NearestNeighbors
14
+
15
+
16
+ class NearestNeighbor2D:
17
+ """
18
+ 二维最近邻插值
19
+
20
+ 使用最近的已知点的值作为插值结果
21
+ """
22
+
23
+ def __init__(self, metric="euclidean"):
24
+ """
25
+ 初始化NearestNeighbor2D插值器
26
+
27
+ Parameters:
28
+ -----------
29
+ metric : str, default='euclidean'
30
+ 距离度量方式,可选:
31
+ - 'euclidean': 欧几里得距离
32
+ - 'manhattan': 曼哈顿距离
33
+ - 'chebyshev': 切比雪夫距离
34
+ - 'minkowski': 闵可夫斯基距离
35
+ """
36
+ self.metric = metric
37
+ self.tree = None
38
+ self.values = None
39
+
40
+ def fit(self, xyzv: np.ndarray):
41
+ """
42
+ 训练最近邻模型
43
+
44
+ Parameters:
45
+ -----------
46
+ xyzv : np.ndarray, shape (N, 3)
47
+ 已知点数据,每行为 [x, y, z] (对于2D插值,z为插值目标值)
48
+
49
+ Returns:
50
+ --------
51
+ self : NearestNeighbor2D
52
+ 返回自身以支持链式调用
53
+ """
54
+ xyzv = np.atleast_2d(xyzv)
55
+ if xyzv.shape[1] != 3:
56
+ raise ValueError("输入数据必须是3列:[x, y, z]")
57
+
58
+ # 构建KD树用于快速最近邻搜索
59
+ self.tree = cKDTree(xyzv[:, :2]) # 只使用x, y坐标
60
+ self.values = xyzv[:, 2] # z值
61
+
62
+ return self
63
+
64
+ def predict(self, xy: np.ndarray):
65
+ """
66
+ 在指定位置进行插值预测
67
+
68
+ Parameters:
69
+ -----------
70
+ xy : np.ndarray, shape (M, 2) or (2,)
71
+ 待插值点的坐标 [x, y]
72
+
73
+ Returns:
74
+ --------
75
+ float or np.ndarray
76
+ - 单点输入 (2,): 返回标量值
77
+ - 多点输入 (M, 2): 返回数组 shape (M,)
78
+ """
79
+ if self.tree is None:
80
+ raise ValueError("模型尚未训练,请先调用 fit() 方法")
81
+
82
+ # 检查输入是单点还是多点
83
+ is_single_point = xy.ndim == 1 or (xy.ndim == 2 and xy.shape[0] == 1)
84
+
85
+ xy = np.atleast_2d(xy)
86
+ if xy.shape[1] != 2:
87
+ raise ValueError("预测点坐标必须是2列:[x, y]")
88
+
89
+ # 查找最近邻
90
+ distances, indices = self.tree.query(xy)
91
+
92
+ # 返回最近邻的值
93
+ z = self.values[indices]
94
+
95
+ # 根据输入类型返回相应格式
96
+ if is_single_point:
97
+ return float(z[0]) # 单点返回标量
98
+ else:
99
+ return z # 多点返回数组
100
+
101
+
102
+ class NearestNeighbor3D:
103
+ """
104
+ 三维最近邻插值
105
+
106
+ 在三维空间中进行最近邻插值
107
+ """
108
+
109
+ def __init__(self, metric="euclidean"):
110
+ """
111
+ 初始化NearestNeighbor3D插值器
112
+
113
+ Parameters:
114
+ -----------
115
+ metric : str, default='euclidean'
116
+ 距离度量方式
117
+ """
118
+ self.metric = metric
119
+ self.tree = None
120
+ self.values = None
121
+
122
+ def fit(self, xyzv: np.ndarray):
123
+ """
124
+ 训练最近邻3D模型
125
+
126
+ Parameters:
127
+ -----------
128
+ xyzv : np.ndarray, shape (N, 4)
129
+ 已知点数据,每行为 [x, y, z, value]
130
+
131
+ Returns:
132
+ --------
133
+ self : NearestNeighbor3D
134
+ 返回自身以支持链式调用
135
+ """
136
+ xyzv = np.atleast_2d(xyzv)
137
+ if xyzv.shape[1] != 4:
138
+ raise ValueError("输入数据必须是4列:[x, y, z, value]")
139
+
140
+ # 构建KD树用于快速最近邻搜索
141
+ self.tree = cKDTree(xyzv[:, :3]) # 使用x, y, z坐标
142
+ self.values = xyzv[:, 3] # 属性值
143
+
144
+ return self
145
+
146
+ def predict(self, xyz: np.ndarray):
147
+ """
148
+ 在指定位置进行插值预测
149
+
150
+ Parameters:
151
+ -----------
152
+ xyz : np.ndarray, shape (M, 3) or (3,)
153
+ 待插值点的坐标 [x, y, z]
154
+
155
+ Returns:
156
+ --------
157
+ float or np.ndarray
158
+ - 单点输入 (3,): 返回标量值
159
+ - 多点输入 (M, 3): 返回数组 shape (M,)
160
+ """
161
+ if self.tree is None:
162
+ raise ValueError("模型尚未训练,请先调用 fit() 方法")
163
+
164
+ # 检查输入是单点还是多点
165
+ is_single_point = xyz.ndim == 1 or (xyz.ndim == 2 and xyz.shape[0] == 1)
166
+
167
+ xyz = np.atleast_2d(xyz)
168
+ if xyz.shape[1] != 3:
169
+ raise ValueError("预测点坐标必须是3列:[x, y, z]")
170
+
171
+ # 查找最近邻
172
+ distances, indices = self.tree.query(xyz)
173
+
174
+ # 返回最近邻的值
175
+ v = self.values[indices]
176
+
177
+ # 根据输入类型返回相应格式
178
+ if is_single_point:
179
+ return float(v[0]) # 单点返回标量
180
+ else:
181
+ return v # 多点返回数组
182
+
183
+ def predict_grid(self, x_range, y_range, z_range, resolution=None):
184
+ """
185
+ 在规则网格上进行预测
186
+
187
+ Parameters:
188
+ -----------
189
+ x_range : tuple
190
+ x方向的范围 (x_min, x_max)
191
+ y_range : tuple
192
+ y方向的范围 (y_min, y_max)
193
+ z_range : tuple
194
+ z方向的范围 (z_min, z_max)
195
+ resolution : tuple, optional
196
+ 网格分辨率 (nx, ny, nz),默认为 (50, 50, 50)
197
+
198
+ Returns:
199
+ --------
200
+ tuple
201
+ (grid_x, grid_y, grid_z, predictions)
202
+ - grid_x, grid_y, grid_z: 网格坐标
203
+ - predictions: 预测值网格
204
+ """
205
+ if self.tree is None:
206
+ raise ValueError("模型尚未训练,请先调用 fit() 方法")
207
+
208
+ if resolution is None:
209
+ resolution = (50, 50, 50)
210
+
211
+ # 创建网格
212
+ x = np.linspace(x_range[0], x_range[1], resolution[0])
213
+ y = np.linspace(y_range[0], y_range[1], resolution[1])
214
+ z = np.linspace(z_range[0], z_range[1], resolution[2])
215
+
216
+ grid_x, grid_y, grid_z = np.meshgrid(x, y, z, indexing="ij")
217
+
218
+ # 将网格点展平进行预测
219
+ grid_points = np.column_stack([grid_x.ravel(), grid_y.ravel(), grid_z.ravel()])
220
+
221
+ predictions_flat = self.predict(grid_points)
222
+ predictions = predictions_flat.reshape(grid_x.shape)
223
+
224
+ return grid_x, grid_y, grid_z, predictions
225
+
226
+
227
+ class KNearestNeighbor:
228
+ """
229
+ K最近邻插值
230
+
231
+ 使用K个最近邻点的加权平均值进行插值
232
+ """
233
+
234
+ def __init__(self, k=3, weights="uniform", metric="euclidean"):
235
+ """
236
+ 初始化K最近邻插值器
237
+
238
+ Parameters:
239
+ -----------
240
+ k : int, default=3
241
+ 最近邻的数量
242
+ weights : str, default='uniform'
243
+ 权重计算方式:
244
+ - 'uniform': 均匀权重
245
+ - 'distance': 距离反比权重
246
+ metric : str, default='euclidean'
247
+ 距离度量方式
248
+ """
249
+ self.k = k
250
+ self.weights = weights
251
+ self.metric = metric
252
+ self.nn_model = None
253
+ self.points = None
254
+ self.values = None
255
+
256
+ def fit(self, xyzv: np.ndarray):
257
+ """
258
+ 训练K最近邻模型
259
+
260
+ Parameters:
261
+ -----------
262
+ xyzv : np.ndarray, shape (N, D+1)
263
+ 已知点数据,前D列为坐标,最后一列为值
264
+
265
+ Returns:
266
+ --------
267
+ self : KNearestNeighbor
268
+ 返回自身以支持链式调用
269
+ """
270
+ xyzv = np.atleast_2d(xyzv)
271
+ if xyzv.shape[1] < 2:
272
+ raise ValueError("输入数据至少需要2列:[坐标..., value]")
273
+
274
+ self.points = xyzv[:, :-1] # 前面的列为坐标
275
+ self.values = xyzv[:, -1] # 最后一列为值
276
+
277
+ if self.k > len(self.points):
278
+ raise ValueError(f"k={self.k} 不能大于数据点数量 {len(self.points)}")
279
+
280
+ # 使用sklearn的NearestNeighbors
281
+ self.nn_model = NearestNeighbors(n_neighbors=self.k, metric=self.metric)
282
+ self.nn_model.fit(self.points)
283
+
284
+ return self
285
+
286
+ def predict(self, query_points: np.ndarray) -> np.ndarray:
287
+ """
288
+ 在指定位置进行插值预测
289
+
290
+ Parameters:
291
+ -----------
292
+ query_points : np.ndarray, shape (M, D)
293
+ 查询点坐标
294
+
295
+ Returns:
296
+ --------
297
+ np.ndarray, shape (M,)
298
+ 插值结果
299
+ """
300
+ if self.nn_model is None:
301
+ raise ValueError("模型尚未训练,请先调用 fit() 方法")
302
+
303
+ query_points = np.atleast_2d(query_points)
304
+
305
+ # 查找K个最近邻
306
+ distances, indices = self.nn_model.kneighbors(query_points)
307
+
308
+ # 获取最近邻的值
309
+ neighbor_values = self.values[indices] # shape: (M, k)
310
+
311
+ if self.weights == "uniform":
312
+ # 均匀权重:简单平均
313
+ predictions = np.mean(neighbor_values, axis=1)
314
+ elif self.weights == "distance":
315
+ # 距离权重:距离越近权重越大
316
+ # 避免除零错误
317
+ distances = np.maximum(distances, 1e-10)
318
+ weights = 1.0 / distances
319
+
320
+ # 归一化权重
321
+ weights = weights / np.sum(weights, axis=1, keepdims=True)
322
+
323
+ # 加权平均
324
+ predictions = np.sum(neighbor_values * weights, axis=1)
325
+ else:
326
+ raise ValueError(f"不支持的权重类型: {self.weights}")
327
+
328
+ return predictions.squeeze() if predictions.shape[0] == 1 else predictions
329
+
330
+
331
+ class AdaptiveNearestNeighbor:
332
+ """
333
+ 自适应最近邻插值
334
+
335
+ 根据局部数据密度自动调整邻居数量
336
+ """
337
+
338
+ def __init__(self, min_k=1, max_k=10, radius_factor=1.0, metric="euclidean"):
339
+ """
340
+ 初始化自适应最近邻插值器
341
+
342
+ Parameters:
343
+ -----------
344
+ min_k : int, default=1
345
+ 最小邻居数量
346
+ max_k : int, default=10
347
+ 最大邻居数量
348
+ radius_factor : float, default=1.0
349
+ 搜索半径因子
350
+ metric : str, default='euclidean'
351
+ 距离度量方式
352
+ """
353
+ self.min_k = min_k
354
+ self.max_k = max_k
355
+ self.radius_factor = radius_factor
356
+ self.metric = metric
357
+ self.tree = None
358
+ self.points = None
359
+ self.values = None
360
+
361
+ def fit(self, xyzv: np.ndarray):
362
+ """
363
+ 训练自适应最近邻模型
364
+
365
+ Parameters:
366
+ -----------
367
+ xyzv : np.ndarray, shape (N, D+1)
368
+ 已知点数据,前D列为坐标,最后一列为值
369
+
370
+ Returns:
371
+ --------
372
+ self : AdaptiveNearestNeighbor
373
+ 返回自身以支持链式调用
374
+ """
375
+ xyzv = np.atleast_2d(xyzv)
376
+ if xyzv.shape[1] < 2:
377
+ raise ValueError("输入数据至少需要2列:[坐标..., value]")
378
+
379
+ self.points = xyzv[:, :-1] # 前面的列为坐标
380
+ self.values = xyzv[:, -1] # 最后一列为值
381
+
382
+ # 构建KD树
383
+ self.tree = cKDTree(self.points)
384
+
385
+ return self
386
+
387
+ def predict(self, query_points: np.ndarray) -> np.ndarray:
388
+ """
389
+ 在指定位置进行插值预测
390
+
391
+ Parameters:
392
+ -----------
393
+ query_points : np.ndarray, shape (M, D)
394
+ 查询点坐标
395
+
396
+ Returns:
397
+ --------
398
+ np.ndarray, shape (M,)
399
+ 插值结果
400
+ """
401
+ if self.tree is None:
402
+ raise ValueError("模型尚未训练,请先调用 fit() 方法")
403
+
404
+ query_points = np.atleast_2d(query_points)
405
+ predictions = []
406
+
407
+ for query_point in query_points:
408
+ # 估计局部密度
409
+ distances, indices = self.tree.query(
410
+ query_point, k=min(self.max_k, len(self.points))
411
+ )
412
+
413
+ # 根据距离分布确定邻居数量
414
+ if len(distances) > 1:
415
+ # 计算距离的变化率
416
+ distance_ratios = distances[1:] / distances[:-1]
417
+ # 找到距离突然增大的位置
418
+ jump_idx = np.where(distance_ratios > 2.0)[0]
419
+
420
+ if len(jump_idx) > 0:
421
+ k = max(self.min_k, jump_idx[0] + 1)
422
+ else:
423
+ k = self.max_k
424
+ else:
425
+ k = 1
426
+
427
+ k = min(k, len(self.points))
428
+
429
+ # 使用确定的k进行插值
430
+ distances_k = distances[:k]
431
+ indices_k = indices[:k]
432
+ values_k = self.values[indices_k]
433
+
434
+ if k == 1:
435
+ prediction = values_k[0]
436
+ else:
437
+ # 距离权重
438
+ weights = 1.0 / np.maximum(distances_k, 1e-10)
439
+ weights = weights / np.sum(weights)
440
+ prediction = np.sum(values_k * weights)
441
+
442
+ predictions.append(prediction)
443
+
444
+ predictions = np.array(predictions)
445
+ return predictions.squeeze() if predictions.shape[0] == 1 else predictions