├── .gitignore
├── LICENSE
├── README.md
├── examples
├── IDW2D.py
├── IDW3D.py
├── OK2D.py
├── OK2DWithNestVariogram.py
├── OK3D.py
├── OK3DWithNestVariogram.py
├── SK2D.py
├── SK2DWithNestVariogram.py
├── SK3D.py
├── SK3DWithNestVariogram.py
├── __init__.py
├── data
│ ├── AustraliaTemperature20210101.csv
│ ├── sample_data.gslib
│ └── tatitlek_815_mhhw_2011.nc
├── gui
│ └── guiDemo.py
├── ncFileUtil.py
├── nestVariogram.py
├── plotUtils.py
├── temperature.py
├── tf
│ ├── IDW2D.py
│ ├── IDW3D.py
│ ├── OK2D.py
│ ├── OK2DWithNestVariogram.py
│ ├── OK3D.py
│ ├── OK3DWithNestVariogram.py
│ ├── SK2D.py
│ ├── SK2DWithNestVariogram.py
│ ├── SK3D.py
│ └── SK3DWithNestVariogram.py
└── variogram.py
├── figs
└── OK3D.jpg
├── requirements.txt
└── src
└── tfinterpy
├── __init__.py
├── grid.py
├── gslib
├── __init__.py
└── fileUtils.py
├── gui
├── __init__.py
├── canvas.py
├── tool.py
├── tool.ui
└── uiTool.py
├── idw.py
├── krige.py
├── tf
├── __init__.py
├── commonLayer.py
├── idw.py
├── krige.py
└── variogramLayer.py
├── utils.py
├── variogram.py
├── variogramExp.py
├── variogramModel.py
└── vtk
├── __init__.py
├── colorMap.py
├── fileUtils.py
└── rendering.py
/.gitignore:
--------------------------------------------------------------------------------
1 | *.log
2 | __pycache__/
3 | .idea/
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## TFInterpy
2 | TFInterpy is a Python package for spatial interpolation. A high-performance version of several interpolation algorithms is implemented based on TensorFlow. Including parallelizable IDW and Kriging algorithms. So far, tfinterpy is the **fastest open source Kriging** algorithm, which can reduce the operation time of large-scale interpolation tasks by an order of magnitude
3 |
4 | ## Link to our paper
5 | [TFInterpy: A high-performance spatial interpolation Python package](https://www.sciencedirect.com/science/article/pii/S2352711022001479)
6 |
7 | (https://doi.org/10.1016/j.softx.2022.101229)
8 |
9 | ### Performance comparison (unit: second)
10 |
11 | | Grid size | GeostatsPy-OK | PyKrige-OK | TFInterpy-OK | TFInterpy-TFOK(GPU) | TFInterpy-TFOK(CPU) |
12 | | :-----: | :-----: | :-----: | :-----: | :-----: | :-----: |
13 | | 1x104 | 23.977 | 1.258 | 0.828 | 2.070 | 0.979 |
14 | | 1x105 | 230.299 | 12.264 | 8.140 | 6.239 | 2.067 |
15 | | 1x106 | 2011.351 | 121.711 | 82.397 | 45.737 | 11.683 |
16 | | 1x107 | 2784.843 | 1250.980 | 849.974 | 452.567 | 112.331 |
17 |
18 | ### Screenshots
19 | Snapshot of GUI tool.
20 | 
21 |
22 | #### Requirements
23 |
24 | **Minimum usage requirements:** Python 3+, Numpy, SciPy
25 |
26 | **TensorFlow based algorithm:** TensorFlow 2
27 |
28 | **GSLIB file support:** Pandas
29 |
30 | **3D visualization:** VTK
31 |
32 | **GUI Tool:** PyQT5
33 |
34 | -----
35 |
36 | # Usage
37 |
38 | #### Install tfinterpy
39 | ```
40 | pip install tfinterpy
41 | ```
42 |
43 | #### Then install dependencies
44 |
45 | **Full dependencies** : (To avoid package version issues, the specific version numbers tested in Python3.9 are listed here)
46 | ```
47 | pip install matplotlib==3.9.4
48 | pip install numpy==2.0.2
49 | pip install pandas==2.2.3
50 | pip install PyQt5==5.15.11
51 | pip install scipy==1.13.1
52 | pip install tensorflow==2.18.0
53 | pip install vtk==9.4.1
54 | ```
55 |
56 | **Notice!** You may do not need to install all dependencies
57 | - If you only need to use the most basic interpolation algorithm, install the following package. (see "examples/" for usage)
58 | ```
59 | pip install numpy==2.0.2
60 | pip install scipy==1.13.1
61 | ```
62 | - If you need to use TensorFlow-based interpolation algorithms, you need to install tensorflow. (see "examples/tf" for usage)
63 | ```
64 | pip install tensorflow==2.18.0
65 | ```
66 | or (Use GPU for computing)
67 | ```
68 | pip install tensorflow-gpu==2.18.0
69 | ```
70 | - If you need to use the built-in GUI tools (see "examples/gui" for usage) provided, please install full dependencies as above list.
71 |
72 | ### Run examples
73 |
74 | All of the sample code can be found in the "examples" folder, the examples directory is recommended as the working directory.
75 |
76 | netCDF4 needs to be installed first to load the data.
77 | ```
78 | pip install netCDF4==1.7.2
79 | ```
80 |
81 |
82 |
--------------------------------------------------------------------------------
/examples/IDW2D.py:
--------------------------------------------------------------------------------
1 | from tfinterpy.idw import IDW
2 | from tfinterpy.grid import Grid2D
3 | from ncFileUtil import getSamples
4 | from plotUtils import *
5 | import numpy as np
6 | import random
7 |
8 | if __name__ == "__main__":
9 | random.seed(1)
10 | W, H = 100, 100
11 | M = 100
12 | offset = (400, 800)
13 | N = 8
14 |
15 | # Get sample points and original elevation data from netcdf file
16 | # containing Digital Elevation Model data.
17 | samples, lats, lons, ele = getSamples("data/tatitlek_815_mhhw_2011.nc", 'lat', 'lon', 'Band1',
18 | offset, (W, H), M)
19 | # Create linear 2D grid.
20 | grid = Grid2D()
21 | grid.rectlinear((W, H), (1, W), (1, H))
22 |
23 | exe = IDW(samples)# Create a idw interpolator.
24 | grid.pro = exe.execute(grid.points(), N)# Perform interpolation of all points in the grid.
25 |
26 | print(exe.crossValidate(N))# Perform leave-one-out validation and print result.
27 | print(exe.crossValidateKFold(10, N))# Perform k-fold validation and print result.
28 |
29 | pro = grid.pro.reshape((grid.dim[1], grid.dim[0]))# Reshape properties as 2d ndarray.
30 | plt.figure()
31 | plt.subplot(221)
32 | img2d(ele, title="Origin")# Plotting original elevation data.
33 | plt.subplot(222)
34 | img2d(pro, title="IDW")# Plotting interpolation results.
35 | absdiff = np.abs(pro - ele)
36 | plt.subplot(223)
37 | img2d(absdiff, title="AE")# Plotting absolute errors.
38 | print('result MAE:', np.mean(absdiff))
39 | plt.show()
40 |
--------------------------------------------------------------------------------
/examples/IDW3D.py:
--------------------------------------------------------------------------------
1 | from tfinterpy.idw import IDW
2 | from tfinterpy.grid import Grid3D
3 | from tfinterpy.gslib.fileUtils import readGslibPoints
4 | import tfinterpy.vtk.colorMap as CM
5 | from tfinterpy.vtk.rendering import createGridActor, rendering
6 | from tfinterpy.vtk.fileUtils import saveVTKGrid
7 |
8 | if __name__ == "__main__":
9 | filePath = "data/sample_data.gslib"
10 | N = 8
11 | df = readGslibPoints(filePath)# Read 3d points from gslib file.
12 | print(df.describe())
13 | samples = df[['x', 'y', 'z', 'porosity']].values
14 |
15 | # Create linear 3D grid.
16 | grid = Grid3D()
17 | grid.rectlinear((100, 100, 10), (samples[:, 0].min(), samples[:, 0].max()),
18 | (samples[:, 1].min(), samples[:, 1].max()), (samples[:, 2].min(), samples[:, 2].max()))
19 | exe = IDW(samples, '3d')# Create a idw interpolator.
20 |
21 | grid.pro = exe.execute(grid.points(), N)# Perform interpolation of all points in the grid.
22 | print(exe.crossValidate(N))# Perform leave-one-out validation and print result.
23 | print(exe.crossValidateKFold(10, N))# Perform k-fold validation and print result.
24 |
25 | # Create an actor representing a rectilinear grid and use the interpolation results for color mapping.
26 | actor = createGridActor(*grid.dim, grid.x, grid.y, grid.z, grid.pro,
27 | [samples[:, 3].min(), samples[:, 3].max()], CM.Rainbow)
28 | rendering(actor)# Rendering vtkActor.
29 | saveVTKGrid('savedData/grid.vtk', actor.GetMapper().GetInput())# Save grid data to vtk file.
30 |
--------------------------------------------------------------------------------
/examples/OK2D.py:
--------------------------------------------------------------------------------
1 | from tfinterpy.krige import OK
2 | from tfinterpy.grid import Grid2D
3 | from ncFileUtil import getSamples
4 | from plotUtils import *
5 | from tfinterpy.variogram import calculateDefaultVariogram2D
6 | import numpy as np
7 | import random
8 |
9 | if __name__ == "__main__":
10 | random.seed(1)
11 | filePath = "data/tatitlek_815_mhhw_2011.nc"
12 | W, H = 50, 100
13 | M = 80
14 | offset = (400, 800)
15 | N = 8
16 |
17 | # Get sample points and original elevation data from netcdf file
18 | # containing Digital Elevation Model data.
19 | samples, lats, lons, ele = getSamples(filePath, 'lat', 'lon', 'Band1', offset, (W, H), M)
20 |
21 | # Create linear 2D grid.
22 | grid = Grid2D()
23 | grid.rectlinear((W, H), (1, W), (1, H))
24 |
25 | # Calculate a default variogram function.
26 | vb = calculateDefaultVariogram2D(samples)
27 | exe = OK(samples)# Create a ok interpolator.
28 | # Perform interpolation of all points in the grid.
29 | grid.pro, grid.sigma = exe.execute(grid.points(), N, vb.getVariogram())
30 |
31 | print(exe.crossValidate(N, vb.getVariogram()))# Perform leave-one-out validation and print result.
32 | print(exe.crossValidateKFold(10, N, vb.getVariogram()))# Perform k-fold validation and print result.
33 |
34 | grid.pro.resize((grid.dim[1], grid.dim[0]))# Reshape properties as 2d ndarray.
35 | grid.sigma.resize((grid.dim[1], grid.dim[0]))# Reshape kriging variances as 2d ndarray.
36 | ae = np.abs(grid.pro - ele)
37 | print("mae:", np.mean(ae))
38 | plt.subplot(221)
39 | img2d(ele, title="origin")# Plotting original elevation data.
40 | plt.subplot(222)
41 | img2d(grid.pro, title="estimate")# Plotting interpolation results.
42 | plt.subplot(223)
43 | img2d(ae, title="error")# Plotting absolute errors.
44 | plt.subplot(224)
45 | img2d(grid.sigma, title="krige variance")# Plotting kriging variances.
46 | plt.show()
47 |
--------------------------------------------------------------------------------
/examples/OK2DWithNestVariogram.py:
--------------------------------------------------------------------------------
1 | from tfinterpy.krige import OK
2 | from tfinterpy.grid import Grid2D
3 | from ncFileUtil import getSamples
4 | from plotUtils import *
5 | from tfinterpy.variogram import calculateOmnidirectionalVariogram2D
6 | from tfinterpy.utils import calcVecs
7 | import numpy as np
8 | import random
9 |
10 | if __name__ == "__main__":
11 | random.seed(1)
12 | filePath = "data/tatitlek_815_mhhw_2011.nc"
13 | W, H = 100, 100
14 | M = 100
15 | offset = (400, 800)
16 | N = 8
17 |
18 | # Get sample points and original elevation data from netcdf file
19 | # containing Digital Elevation Model data.
20 | samples, lats, lons, ele = getSamples(filePath, 'lat', 'lon', 'Band1', offset, (W, H), M)
21 |
22 | # Create linear 2D grid.
23 | grid = Grid2D()
24 | grid.rectlinear((W, H), (1, W), (1, H))
25 |
26 | # Calculate a nested variogram function.
27 | nv, vbs = calculateOmnidirectionalVariogram2D(samples, model=None)
28 | for vb in vbs:
29 | plt.figure()
30 | vb.showVariogram()
31 | plt.show()
32 |
33 | exe = OK(samples)# Create a ok interpolator.
34 | # Perform interpolation of all points in the grid.
35 | grid.pro, grid.sigma = exe.execute(grid.points(), N, nv)
36 |
37 | print(exe.crossValidate(N, nv))# Perform leave-one-out validation and print result.
38 | print(exe.crossValidateKFold(10, N, nv))# Perform k-fold validation and print result.
39 |
40 | grid.pro.resize((grid.dim[1], grid.dim[0]))# Reshape properties as 2d ndarray.
41 | grid.sigma.resize((grid.dim[1], grid.dim[0]))# Reshape kriging variances as 2d ndarray.
42 |
43 | ae = np.abs(grid.pro - ele)
44 | print("mae:", np.mean(ae))
45 | plt.subplot(221)
46 | img2d(ele, title="origin")# Plotting original elevation data.
47 | plt.subplot(222)
48 | img2d(grid.pro, title="estimate")# Plotting interpolation results.
49 | plt.subplot(223)
50 | img2d(ae, title="error")# Plotting absolute errors.
51 | plt.subplot(224)
52 | img2d(grid.sigma, title="krige variance")# Plotting kriging variances.
53 | plt.show()
54 |
--------------------------------------------------------------------------------
/examples/OK3D.py:
--------------------------------------------------------------------------------
1 | from tfinterpy.krige import OK
2 | from tfinterpy.grid import Grid3D
3 | from tfinterpy.variogram import calculateDefaultVariogram3D
4 | from tfinterpy.gslib.fileUtils import readGslibPoints
5 | import tfinterpy.vtk.colorMap as CM
6 | from tfinterpy.vtk.rendering import createGridActor, rendering
7 | from tfinterpy.vtk.fileUtils import saveVTKGrid
8 | import matplotlib.pyplot as plt
9 |
10 | if __name__ == "__main__":
11 | filePath = "data/sample_data.gslib"
12 | N = 8
13 | df = readGslibPoints(filePath)# Read 3d points from gslib file.
14 | print(df.describe())
15 | samples = df[['x', 'y', 'z', 'porosity']].values
16 |
17 | # Create linear 3D grid.
18 | grid = Grid3D()
19 | grid.rectlinear((100, 100, 10), (samples[:, 0].min(), samples[:, 0].max()),
20 | (samples[:, 1].min(), samples[:, 1].max()), (samples[:, 2].min(), samples[:, 2].max()))
21 | exe = OK(samples, '3d')# Create a ok interpolator.
22 |
23 | vb = calculateDefaultVariogram3D(samples)# Calculate a default variogram function.
24 | plt.figure()
25 | vb.showVariogram()
26 | plt.show()
27 |
28 | # Perform interpolation of all points in the grid.
29 | grid.pro, grid.sigma = exe.execute(grid.points(), N, vb.getVariogram())
30 | print(exe.crossValidate(N, vb.getVariogram()))# Perform leave-one-out validation and print result.
31 | print(exe.crossValidateKFold(10, N, vb.getVariogram()))# Perform k-fold validation and print result.
32 |
33 | # Create an actor representing a rectilinear grid and use the interpolation results for color mapping.
34 | actor = createGridActor(*grid.dim, grid.x, grid.y, grid.z, grid.pro,
35 | [samples[:, 3].min(), samples[:, 3].max()], CM.Rainbow)
36 | rendering(actor)# Rendering vtkActor.
37 | # Create an actor representing a rectilinear grid and use the kriging variances for color mapping.
38 | actor = createGridActor(*grid.dim, grid.x, grid.y, grid.z, grid.sigma, None, CM.Rainbow)
39 | rendering(actor)# Rendering vtkActor.
40 | saveVTKGrid('savedData/grid.vtk', actor.GetMapper().GetInput())# Save grid data(kriging variances) to vtk file.
41 |
--------------------------------------------------------------------------------
/examples/OK3DWithNestVariogram.py:
--------------------------------------------------------------------------------
1 | from tfinterpy.krige import OK
2 | from tfinterpy.grid import Grid3D
3 | from tfinterpy.variogram import calculateOmnidirectionalVariogram3D
4 | from tfinterpy.gslib.fileUtils import readGslibPoints
5 | from tfinterpy.vtk.rendering import createGridActor, rendering
6 | import tfinterpy.vtk.colorMap as CM
7 | from tfinterpy.vtk.fileUtils import saveVTKGrid
8 | from tfinterpy.utils import calcVecs
9 | import matplotlib.pyplot as plt
10 |
11 | if __name__ == "__main__":
12 | filePath = "data/sample_data.gslib"
13 | N = 8
14 | df = readGslibPoints(filePath)# Read 3d points from gslib file.
15 | print(df.describe())
16 | samples = df[['x', 'y', 'z', 'porosity']].values
17 |
18 | # Create linear 3D grid.
19 | grid = Grid3D()
20 | grid.rectlinear((100, 100, 10), (samples[:, 0].min(), samples[:, 0].max()),
21 | (samples[:, 1].min(), samples[:, 1].max()), (samples[:, 2].min(), samples[:, 2].max()))
22 |
23 | # Calculate a nested variogram function.
24 | nestVariogram, variogramBuilders = calculateOmnidirectionalVariogram3D(samples)
25 | for vb in variogramBuilders:
26 | plt.figure()
27 | vb.showVariogram()
28 | plt.show()
29 |
30 | exe = OK(samples, '3d')# Create a ok interpolator.
31 | # Perform interpolation of all points in the grid.
32 | grid.pro, grid.sigma = exe.execute(grid.points(), N, nestVariogram)
33 |
34 | print(exe.crossValidate(N, nestVariogram))# Perform leave-one-out validation and print result.
35 | print(exe.crossValidateKFold(10, N, nestVariogram))# Perform k-fold validation and print result.
36 | # Create an actor representing a rectilinear grid and use the interpolation results for color mapping.
37 | actor = createGridActor(*grid.dim, grid.x, grid.y, grid.z, grid.pro,
38 | [samples[:, 3].min(), samples[:, 3].max()], CM.Rainbow)
39 | rendering(actor)# Rendering vtkActor.
40 | # Create an actor representing a rectilinear grid and use the kriging variances for color mapping.
41 | actor = createGridActor(*grid.dim, grid.x, grid.y, grid.z, grid.sigma, None, CM.Rainbow)
42 | rendering(actor)# Rendering vtkActor.
43 | saveVTKGrid('savedData/grid.vtk', actor.GetMapper().GetInput())# Save grid data(kriging variances) to vtk file.
44 |
--------------------------------------------------------------------------------
/examples/SK2D.py:
--------------------------------------------------------------------------------
1 | from tfinterpy.krige import SK
2 | from tfinterpy.grid import Grid2D
3 | from tfinterpy.variogram import calculateDefaultVariogram2D
4 | from ncFileUtil import getSamples
5 | from plotUtils import *
6 | import numpy as np
7 | import random
8 |
9 | if __name__ == "__main__":
10 | random.seed(1)
11 | filePath = "data/tatitlek_815_mhhw_2011.nc"
12 | W, H = 100, 100
13 | M = 100
14 | offset = (400, 800)
15 | N = 8
16 |
17 | # Get sample points and original elevation data from netcdf file
18 | # containing Digital Elevation Model data.
19 | samples, lats, lons, ele = getSamples(filePath, 'lat', 'lon', 'Band1', offset, (W, H), M)
20 |
21 | # Create linear 2D grid.
22 | grid = Grid2D()
23 | grid.rectlinear((W, H), (1, W), (1, H))
24 |
25 | # Calculate a default variogram function.
26 | vb = calculateDefaultVariogram2D(samples)
27 | exe = SK(samples)# Create a sk interpolator.
28 | # Perform interpolation of all points in the grid.
29 | grid.pro, grid.sigma = exe.execute(grid.points(), N, vb.getVariogram())
30 |
31 | print(exe.crossValidate(N, vb.getVariogram()))# Perform leave-one-out validation and print result.
32 | print(exe.crossValidateKFold(10, N, vb.getVariogram()))# Perform k-fold validation and print result.
33 |
34 | grid.pro.resize((grid.dim[1], grid.dim[0]))# Reshape properties as 2d ndarray.
35 | grid.sigma.resize((grid.dim[1], grid.dim[0]))# Reshape kriging variances as 2d ndarray.
36 | ae = np.abs(grid.pro - ele)
37 | print("mae:", np.mean(ae))
38 | plt.subplot(221)
39 | img2d(ele, title="origin")# Plotting original elevation data.
40 | plt.subplot(222)
41 | img2d(grid.pro, title="estimate")# Plotting interpolation results.
42 | plt.subplot(223)
43 | img2d(ae, title="error")# Plotting absolute errors.
44 | plt.subplot(224)
45 | img2d(grid.sigma, title="krige variance")# Plotting kriging variances.
46 | plt.show()
47 |
--------------------------------------------------------------------------------
/examples/SK2DWithNestVariogram.py:
--------------------------------------------------------------------------------
1 | from tfinterpy.krige import SK
2 | from tfinterpy.grid import Grid2D
3 | from tfinterpy.variogram import calculateDefaultVariogram2D, calculateOmnidirectionalVariogram2D
4 | from tfinterpy.utils import calcVecs
5 | from ncFileUtil import getSamples
6 | from plotUtils import *
7 | import numpy as np
8 | import time
9 |
10 | if __name__ == "__main__":
11 | filePath = "data/tatitlek_815_mhhw_2011.nc"
12 | W, H = 100, 100
13 | M = 100
14 | offset = (400, 800)
15 | N = 8
16 |
17 | # Get sample points and original elevation data from netcdf file
18 | # containing Digital Elevation Model data.
19 | samples, lats, lons, ele = getSamples(filePath, 'lat', 'lon', 'Band1', offset, (W, H), M)
20 |
21 | # Create linear 2D grid.
22 | grid = Grid2D()
23 | grid.rectlinear((W, H), (1, W), (1, H))
24 | exe = SK(samples)# Create a sk interpolator.
25 |
26 | # Calculate a nested variogram function.
27 | nv, vbs = calculateOmnidirectionalVariogram2D(samples)
28 | indice = [i for i in range(0, len(nv.variograms), 2)]
29 | variograms = [nv.variograms[i] for i in indice]
30 | nv.variograms = variograms
31 | nv.unitVectors = nv.unitVectors[indice]
32 |
33 | # Perform interpolation of all points in the grid.
34 | grid.pro, grid.sigma = exe.execute(grid.points(), N, nv)
35 |
36 | print(exe.crossValidate(N, nv))# Perform leave-one-out validation and print result.
37 | print(exe.crossValidateKFold(10, N, nv))# Perform k-fold validation and print result.
38 |
39 | grid.pro.resize((grid.dim[1], grid.dim[0]))
40 | grid.sigma.resize((grid.dim[1], grid.dim[0]))
41 | ae = np.abs(grid.pro - ele)
42 | print("mae:", np.mean(ae))
43 | plt.subplot(221)
44 | img2d(ele, title="origin")# Plotting original elevation data.
45 | plt.subplot(222)
46 | img2d(grid.pro, title="estimate")# Plotting interpolation results.
47 | plt.subplot(223)
48 | img2d(ae, title="error")# Plotting absolute errors.
49 | plt.subplot(224)
50 | img2d(grid.sigma, title="krige variance")# Plotting kriging variances.
51 | plt.show()
52 |
--------------------------------------------------------------------------------
/examples/SK3D.py:
--------------------------------------------------------------------------------
1 | from tfinterpy.krige import SK
2 | from tfinterpy.grid import Grid3D
3 | from tfinterpy.variogram import calculateDefaultVariogram3D
4 | from tfinterpy.gslib.fileUtils import readGslibPoints
5 | from tfinterpy.vtk.rendering import createGridActor, rendering
6 | import tfinterpy.vtk.colorMap as CM
7 | from tfinterpy.vtk.fileUtils import saveVTKGrid
8 | import matplotlib.pyplot as plt
9 |
10 | if __name__ == "__main__":
11 | filePath = "data/sample_data.gslib"
12 | N = 8
13 | df = readGslibPoints(filePath)
14 | print(df.describe())
15 | samples = df[['x', 'y', 'z', 'porosity']].values
16 |
17 | # Create linear 3D grid.
18 | grid = Grid3D()
19 | grid.rectlinear((100, 100, 10), (samples[:, 0].min(), samples[:, 0].max()),
20 | (samples[:, 1].min(), samples[:, 1].max()), (samples[:, 2].min(), samples[:, 2].max()))
21 | exe = SK(samples, '3d')# Create a sk interpolator.
22 |
23 | vb = calculateDefaultVariogram3D(samples)# Calculate a default variogram function.
24 | plt.figure()
25 | vb.showVariogram()
26 | plt.show()
27 |
28 | # Perform interpolation of all points in the grid.
29 | grid.pro, grid.sigma = exe.execute(grid.points(), N, vb.getVariogram())
30 |
31 | print(exe.crossValidate(N, vb.getVariogram()))# Perform leave-one-out validation and print result.
32 | print(exe.crossValidateKFold(10, N, vb.getVariogram()))# Perform k-fold validation and print result.
33 |
34 | # Create an actor representing a rectilinear grid and use the interpolation results for color mapping.
35 | actor = createGridActor(*grid.dim, grid.x, grid.y, grid.z, grid.pro, [samples[:, 3].min(), samples[:, 3].max()])
36 | rendering(actor)# Rendering vtkActor.
37 | # Create an actor representing a rectilinear grid and use the kriging variances for color mapping.
38 | actor = createGridActor(*grid.dim, grid.x, grid.y, grid.z, grid.sigma, None, CM.Rainbow)
39 | rendering(actor)# Rendering vtkActor.
40 | saveVTKGrid('savedData/grid.vtk', actor.GetMapper().GetInput())# Save grid data(kriging variances) to vtk file.
41 |
--------------------------------------------------------------------------------
/examples/SK3DWithNestVariogram.py:
--------------------------------------------------------------------------------
1 | from tfinterpy.krige import SK
2 | from tfinterpy.grid import Grid3D
3 | from tfinterpy.variogram import calculateOmnidirectionalVariogram3D
4 | from tfinterpy.gslib.fileUtils import readGslibPoints
5 | from tfinterpy.vtk.rendering import createGridActor, rendering
6 | import tfinterpy.vtk.colorMap as CM
7 | from tfinterpy.vtk.fileUtils import saveVTKGrid
8 | from tfinterpy.utils import calcVecs
9 | import matplotlib.pyplot as plt
10 |
11 | if __name__ == "__main__":
12 | filePath = "data/sample_data.gslib"
13 | N = 8
14 | df = readGslibPoints(filePath)# Read 3d points from gslib file.
15 | print(df.describe())
16 | samples = df[['x', 'y', 'z', 'porosity']].values
17 |
18 | # Create linear 3D grid.
19 | grid = Grid3D()
20 | grid.rectlinear((100, 100, 10), (samples[:, 0].min(), samples[:, 0].max()),
21 | (samples[:, 1].min(), samples[:, 1].max()), (samples[:, 2].min(), samples[:, 2].max()))
22 |
23 | # Calculate a nested variogram function.
24 | nestVariogram, variogramBuilders = calculateOmnidirectionalVariogram3D(samples)
25 | for vb in variogramBuilders:
26 | plt.figure()
27 | vb.showVariogram()
28 | plt.show()
29 |
30 | exe = SK(samples, '3d')# Create a sk interpolator.
31 | # Perform interpolation of all points in the grid.
32 | grid.pro, grid.sigma = exe.execute(grid.points(), N, nestVariogram)
33 |
34 | print(exe.crossValidate(N, nestVariogram))# Perform leave-one-out validation and print result.
35 | print(exe.crossValidateKFold(10, N, nestVariogram))# Perform k-fold validation and print result.
36 | # Create an actor representing a rectilinear grid and use the interpolation results for color mapping.
37 | actor = createGridActor(*grid.dim, grid.x, grid.y, grid.z, grid.pro, [samples[:, 3].min(), samples[:, 3].max()])
38 | rendering(actor)# Rendering vtkActor.
39 | # Create an actor representing a rectilinear grid and use the kriging variances for color mapping.
40 | actor = createGridActor(*grid.dim, grid.x, grid.y, grid.z, grid.sigma, None, CM.Rainbow)
41 | rendering(actor)# Rendering vtkActor.
42 | saveVTKGrid('savedData/grid.vtk', actor.GetMapper().GetInput())# Save grid data(kriging variances) to vtk file.
43 |
--------------------------------------------------------------------------------
/examples/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # @Time : 2022/3/10 9:41
3 | # @Author : UCCU
4 |
--------------------------------------------------------------------------------
/examples/data/AustraliaTemperature20210101.csv:
--------------------------------------------------------------------------------
1 | STATION,NAME,LATITUDE,LONGITUDE,ELEVATION,TEMP
2 | 95740099999,"GUNNEDAH AIRPORT AWS, AS",-30.95,150.25,263.0,69.9
3 | 94911099999,"YANAKIE, AS",-38.8,146.2,13.9,67.1
4 | 94886099999,"POUND CREEK, AS",-38.6333333,145.8108333,3.6,67.5
5 | 95292099999,"SOUTH JOHNSTONE EXPERIMENTAL STATION, AS",-17.6,146.0,19.0,79.1
6 | 94833099999,"MOUNT WILLIAM, AS",-37.3,142.6,1150.0,61.2
7 | 94951099999,"DUNALLEY STROUD POINT, AS",-42.9,147.7833333,12.7,61.1
8 | 94768099999,"SYDNEY OBSERVATORY HILL, AS",-33.85,151.2,40.0,65.1
9 | 94846099999,"AIREYS INLET, AS",-38.45,144.1,95.0,64.6
10 | 95370099999,"WILLIAMSON, AS",-22.47,150.18,28.0,80.2
11 | 94171099999,"WEIPA, AS",-12.678611,141.925278,19.2,80.1
12 | 94332099999,"MOUNT ISA, AS",-20.663889,139.488611,341.68,84.3
13 | 94637099999,"KALGOORLIE BOULDER, AS",-30.789444,121.461667,366.67,78.3
14 | 94672099999,"ADELAIDE INTERNATIONAL, AS",-34.945,138.530556,6.09,72.2
15 | 94109099999,"MURGANELLA AIRSTRIP, AS",-11.55,132.9266667,11.5,82.3
16 | 94755099999,"CAMDEN, AS",-34.040278,150.687222,70.1,63.7
17 | 94715099999,"FORBES AIRPORT, AS",-33.3666666,147.9166666,231.0,68.2
18 | 94131099999,"TINDAL, AS",-14.521111,132.377778,135.02,84.8
19 | 94820099999,"NARACOORTE AERODROME, AS",-36.9833333,140.7333333,50.0,77.5
20 | 94860099999,"KILMORE GAP, AS",-37.3833333,144.9666666,528.0,67.2
21 | 95836099999,"TATURA INST SUSTAINABLE AG, AS",-36.4333333,145.2666666,114.0,68.5
22 | 94702099999,"HAY AIRPORT AWS, AS",-34.5333333,144.8333333,92.0,74.5
23 | 94595699999,"TELFER, AS",-21.715,122.228611,295.65,94.0
24 | 95726099999,"ORANGE AIRPORT, AS",-33.3833333,149.1333333,948.0,54.7
25 | 94450099999,"LEONORA AERO, AS",-28.8833333,121.3166666,370.0,91.3
26 | 95121099999,"MIDDLE POINT AWS, AS",-12.6,131.3,15.0,83.5
27 | 95662099999,"MINNIPA DPI, AS",-32.85,135.15,166.0,72.9
28 | 95758099999,"SCONE AIRPORT, AS",-32.0333333,150.8333333,223.0,62.7
29 | 94476099999,"OODNADATTA AIRPORT, AS",-27.55,135.45,117.0,91.8
30 | 94929099999,"BOMBALA AWS, AS",-37.0,149.2333333,762.0,54.5
31 | 94977099999,"HARTZ MOUNTAINS, AS",-43.2,146.7666666,830.0,50.5
32 | 94969099999,"LAUNCESTON TI TREE BEND, AS",-41.4166666,147.1166666,5.0,64.3
33 | 94881099999,"EILDON FIRE TOWER, AS",-37.2166666,145.8333333,638.0,64.4
34 | 95718099999,"COONAMBLE AIRPORT, AS",-30.9833333,148.3833333,182.0,72.8
35 | 94859099999,"REDESDALE, AS",-37.0166666,144.5333333,290.0,69.5
36 | 95670099999,"RAYVILLE PARK, AS",-33.7833333,138.2166666,109.0,75.8
37 | 94398099999,"BLACKWATER, AS",-23.603056,148.806944,200.25,78.9
38 | 94110099999,"OENPELLI AIRPORT, AS",-12.3333333,133.0072222,9.1,81.0
39 | 94776099999,"WILLIAMTOWN, AS",-32.795,151.834444,9.44,66.0
40 | 95369099999,"ST LAWRENCE, AS",-22.35,149.5166666,10.0,78.8
41 | 95981099999,"ST HELENS AERODROME, AS",-41.3333333,148.2666666,49.0,59.2
42 | 94763099999,"PENRITH, AS",-33.7166666,150.6833333,25.0,64.0
43 | 94943099999,"NERRIGA AWS, AS",-35.1166666,150.0833333,625.6,56.4
44 | 95761099999,"HOLSWORTHY AERODROME AWS, AS",-33.9833333,150.95,68.8,64.1
45 | 94782099999,"GOSFORD AWS, AS",-33.4333333,151.3666666,7.0,65.8
46 | 94337099999,"JULIA CREEK, AS",-20.6666666,141.7333333,124.0,80.8
47 | 94294099999,"TOWNSVILLE, AS",-19.2525,146.765278,5.48,79.6
48 | 94903099999,"FALLS CREEK AWS, AS",-36.8666666,147.2666666,1767.0,50.9
49 | 94567099999,"MARYBOROUGH, AS",-25.5166666,152.7166666,11.0,75.0
50 | 95571099999,"GRAFTON RESEARCH STATION, AS",-29.6166666,152.9666666,26.0,72.9
51 | 94562099999,"UNIVERSITY OF QUEENSLAND GATTON, AS",-27.55,152.3333333,94.0,77.0
52 | 95351099999,"BLACKALL AIRPORT, AS",-24.4166666,145.4333333,282.0,82.7
53 | 95721099999,"COWRA AIRPORT AWS, AS",-33.85,148.65,297.0,64.7
54 | 95901099999,"MOUNT BAW BAW, AS",-37.8333333,146.2666666,1520.0,52.6
55 | 94128099999,"DOUGLAS RIVER, AS",-13.8333333,131.1833333,44.0,82.1
56 | 95959099999,"LIAWENEE AWS, AS",-41.9,146.6666666,1056.0,52.0
57 | 95831099999,"WALPEUP RESEARCH, AS",-35.1166666,142.0,105.0,76.9
58 | 94972099999,"SCOTTSDALE WEST MINSTONE ROAD, AS",-41.1666666,147.4833333,198.0,59.6
59 | 95705099999,"YANCO AGRICULTURAL INSTITUTE, AS",-34.6166666,146.4333333,164.0,73.0
60 | 94573099999,"CASINO AIRPORT AWS, AS",-28.8833333,153.05,22.0,74.0
61 | 94150099999,"GOVE AIRPORT, AS",-12.2833333,136.8166666,53.0,77.1
62 | 95565099999,"HERVEY BAY AIRPORT, AS",-25.3166666,152.8833333,15.0,76.3
63 | 95322099999,"RABBIT FLAT, AS",-20.1833333,130.0166666,339.0,87.2
64 | 94463099999,"CURTIN SPRINGS, AS",-25.3166666,131.75,491.0,98.3
65 | 94908099999,"OMEO, AS",-37.1,147.6,690.0,61.8
66 | 94578099999,"BRISBANE AIRPORT, AS",-27.4166666,153.0666666,6.0,75.8
67 | 94603099999,"BADGINGARRA RESEARCH STATION, AS",-30.3333333,115.5333333,275.0,78.7
68 | 95747099999,"MURRURUNDI GAP AWS, AS",-31.7333333,150.8,730.0,57.4
69 | 95659099999,"MINLATON AERO, AS",-34.75,137.5166666,32.0,70.9
70 | 94905099999,"MOUNT HOTHAM AIRPORT, AS",-37.05,147.3333333,1293.0,54.8
71 | 94575099999,"BRISBANE ARCHERFIELD, AS",-27.570278,153.008056,19.2,75.4
72 | 94417099999,"MORAWA AIRPORT, AS",-29.2,116.0166666,272.0,82.3
73 | 95774099999,"MANGROVE MOUNTAIN AWS, AS",-33.2833333,151.2166666,305.0,60.3
74 | 94552099999,"OAKEY, AS",-27.411389,151.735278,406.9,74.3
75 | 94216099999,"KUNUNURRA, AS",-15.778056,128.7075,44.19,89.8
76 | 94875099999,"SHEPPARTON AIRPORT, AS",-36.4333333,145.4,114.0,69.6
77 | 95641099999,"WITCHCLIFFE, AS",-34.0333333,115.1,81.0,68.2
78 | 94595999999,"WANGARATTA, AS",-36.415833,146.306944,153.61,70.2
79 | 94852099999,"BALLARAT AERODROME, AS",-37.5166666,143.7833333,436.0,68.5
80 | 95286099999,"MAREEBA AIRPORT AWS, AS",-17.0666666,145.4333333,473.0,76.0
81 | 94827099999,"NHILL AERODROME, AS",-36.3166666,141.6333333,140.0,75.5
82 | 94326099999,"ALICE SPRINGS, AS",-23.806667,133.902222,545.28,85.4
83 | 95969099999,"CRESSY RESEARCH STATION, AS",-41.7333333,147.0833333,150.0,62.2
84 | 95890099999,"YARRAM AIRPORT, AS",-38.5666666,146.75,18.0,66.2
85 | 94774099999,"NEWCASTLE NOBBYS SIGNAL STATION, AS",-32.9166666,151.7833333,33.0,66.1
86 | 95482099999,"BIRDSVILLE, AS",-25.8975,139.3475,47.85,94.8
87 | 95402099999,"SHARK BAY AIRPORT, AS",-25.9,113.5833333,34.0,78.3
88 | 95807099999,"KINGSTONE AERO, AS",-35.7166666,137.5166666,6.0,66.0
89 | 95480099999,"MARREE AERO, AS",-29.6666666,138.0666666,51.0,89.6
90 | 95204099999,"WEST ROEBUCK, AS",-17.9,122.3166666,32.0,88.0
91 | 94766099999,"CANTERBURY RACECOURSE, AS",-33.9,151.1166666,3.0,65.5
92 | 95667099999,"CLARE HIGH SCHOOL, AS",-33.8166666,138.6,396.0,75.9
93 | 95637099999,"LAKE GRACE, AS",-33.1,118.4666666,286.0,68.9
94 | 94878099999,"HUNTERS HILL, AS",-36.2166666,147.5333333,981.0,59.2
95 | 94913099999,"GELANTIPY, AS",-37.2166666,148.2666666,756.0,58.7
96 | 94685099999,"KADINA, AS",-33.97,137.67,42.0,75.4
97 | 94750099999,"NOWRA, AS",-34.948889,150.536944,121.92,63.7
98 | 94662099999,"CLEVE AERODROME, AS",-33.7166666,136.5,176.0,68.9
99 | 95916099999,"CABRAMURRA SMHEA, AS",-35.9333333,148.3833333,1483.0,51.5
100 | 95638099999,"ESPERANCE AERO, AS",-33.6833333,121.8333333,144.0,65.7
101 | 94935099999,"MALLACOOTA, AS",-37.6,149.7333333,22.0,63.7
102 | 95753099999,"RICHMOND RAAF, AS",-33.6,150.7833333,20.0,63.8
103 | 94964099999,"BUSHY PARK BUSHY PARK ESTATES, AS",-42.7166666,146.9,27.0,61.5
104 | 94854099999,"AVALON AIRPORT, AS",-38.0333333,144.4666666,11.0,70.6
105 | 94691099999,"BROKEN HILL AIRPORT AWS, AS",-32.0,141.4666666,282.0,82.6
106 | 94921099999,"COOMA AIRPORT AWS, AS",-36.3,148.9666666,931.0,56.3
107 | 94856099999,"GEELONG CITY, AS",-38.083,144.333,55.0,68.2
108 | 95527099999,"MOREE AERO, AS",-29.4914,149.8458,218.5,78.9
109 | 94595599999,"GOVE, AS",-12.269444,136.818333,58.52,77.5
110 | 95295099999,"AYR DPI RESEARCH STATION, AS",-19.6166666,147.3833333,12.0,79.3
111 | 95632099999,"BRIDGETOWN, AS",-33.95,116.1333333,179.0,68.7
112 | 94217099999,"ARGYLE AERODROME, AS",-16.6333333,128.45,165.0,91.7
113 | 95957099999,"WYNYARD AIRPORT, AS",-41.0,145.7333333,12.0,62.4
114 | 94863099999,"SHEOAKS AWS, AS",-37.9,144.1166666,237.0,68.7
115 | 95839099999,"HORSHAM AERODROME, AS",-36.6666666,142.1666666,134.0,72.9
116 | 94106099999,"NGUKURR AIRPORT, AS",-14.7166666,134.75,14.0,79.3
117 | 94765099999,"SYDNEY BANKSTOWN, AS",-33.924444,150.988333,8.83,65.3
118 | 94760099999,"HORSLEY EQUESTRIAN CENTRE, AS",-33.85,150.85,100.0,63.2
119 | 94647099999,"EUCLA, AS",-31.6797,128.8792,102.3,66.1
120 | 94595399999,"CURTIN, AS",-17.581389,123.828333,91.44,88.5
121 | 94641099999,"KATANNING, AS",-33.6833333,117.6,321.0,66.0
122 | 94914099999,"COMBIENBAR, AS",-37.3333333,149.0166666,641.0,58.6
123 | 95625099999,"CUNDERDIN AIRFIELD, AS",-31.6166666,117.2166666,217.0,76.9
124 | 95640099999,"WANDERING, AS",-32.6666666,116.6666666,275.0,72.6
125 | 94100099999,"KALUMBURU, AS",-14.3,126.6333333,24.0,85.0
126 | 94811099999,"SECOND VALLEY FOREST, AS",-35.5666666,138.2833333,342.0,61.0
127 | 94926099999,"CANBERRA, AS",-35.306944,149.195,574.85,61.1
128 | 94753099999,"RICHMOND, AS",-33.600556,150.780833,20.42,63.9
129 | 95617099999,"SHANNON, AS",-34.5833333,116.35,191.0,64.5
130 | 95909099999,"THREDBO AWS, AS",-36.5,148.2833333,1368.0,46.7
131 | 94655099999,"TARCOOLA, AS",-30.7166666,134.5833333,124.0,83.9
132 | 94474099999,"PUKATJA, AS",-26.2666666,132.1833333,704.0,87.9
133 | 95952099999,"MOUNT READ, AS",-41.85,145.5333333,1120.0,51.1
134 | 94595799999,"TENNANT CREEK, AS",-19.634444,134.183333,376.73,91.1
135 | 95784099999,"TAREE AIRPORT AWS, AS",-31.8833333,152.5166666,9.0,69.8
136 | 94857099999,"GEELONG RACECOURSE, AS",-38.1666666,144.3666666,35.0,70.8
137 | 94712099999,"YOUNG AIRPORT, AS",-34.25,148.25,381.0,64.7
138 | 94752099999,"BADGERY S CREEK AIRPORT, AS",-33.9,150.7333333,82.0,63.3
139 | 94927099999,"BRAIDWOOD RACECOURSE AWS, AS",-35.4333333,149.7833333,666.0,56.0
140 | 94817099999,"COONAWARRA, AS",-37.3,140.8166666,58.0,76.3
141 | 95305099999,"ONSLOW AIRPORT, AS",-21.6666666,115.1166666,11.0,87.2
142 | 94862099999,"YARRAWONGA, AS",-36.0166666,146.0333333,129.0,71.9
143 | 94376099999,"THANGOOL AIRPORT, AS",-24.4833333,150.5666666,199.0,76.5
144 | 94370099999,"SAMUEL HILL AERO, AS",-22.7333333,150.65,32.0,78.7
145 | 95728099999,"COONABARABRAN AIRPORT AWS, AS",-31.3166666,149.2666666,646.0,64.7
146 | 94596099999,"BALLINA AIRPORT AWS, AS",-28.8333333,153.55,2.0,74.4
147 | 94759099999,"TERREY HILLS AWS, AS",-33.6833333,151.2333333,199.0,61.8
148 | 94105099999,"NOONAMAH AIRSTRIP, AS",-12.6166666,131.05,17.5,82.5
149 | 94308099999,"ROEBOURNE AERO, AS",-20.75,117.15,11.0,91.7
150 | 94260099999,"BURKETOWN AIRPORT, AS",-17.75,139.5333333,6.0,81.1
151 | 95845099999,"MOUNT GELLIBRAND, AS",-38.2333333,143.7833333,262.0,65.5
152 | 94588099999,"GLEN INNES AIRPORT, AS",-29.6833333,151.7,1045.0,65.7
153 | 94381099999,"GLADSTONE AIRPORT, AS",-23.8666666,151.2166666,17.0,79.6
154 | 94653099999,"CEDUNA AMO, AS",-32.1333333,133.7,16.0,67.7
155 | 95960099999,"DEVONPORT AIRPORT, AS",-41.1666666,146.4166666,10.0,63.1
156 | 94600099999,"CAPE NATURALISTE, AS",-33.5333333,115.0166666,110.0,72.9
157 | 94925099999,"TUGGERANONG ISABELLA PLAINS, AS",-35.4166666,149.1,588.0,61.6
158 | 94980099999,"FLINDERS ISLAND AIRPORT, AS",-40.1,148.0,10.0,62.5
159 | 94374099999,"ROCKHAMPTON, AS",-23.381944,150.475278,10.36,79.8
160 | 94542099999,"DALBY AIRPORT, AS",-27.15,151.2666666,348.0,75.3
161 | 95629099999,"DALWALLINU, AS",-30.2833333,116.6666666,326.0,80.2
162 | 94968099999,"LAUNCESTON, AS",-41.545278,147.214167,171.29,60.7
163 | 95734099999,"NARRABRI AIRPORT AWS, AS",-30.3166666,149.8166666,230.0,72.9
164 | 94757099999,"CAMBELL TOWN MOUNT ANNAN, AS",-34.0666666,150.7666666,112.0,63.1
165 | 95566099999,"BEERBURRUM FOREST STATION, AS",-26.95,152.9666666,36.0,72.7
166 | 95676099999,"EDINBURGH, AS",-34.7025,138.620833,20.42,75.9
167 | 94930099999,"MOUNT NOWA NOWA, AS",-37.7,148.0833333,350.0,64.8
168 | 94807099999,"PARDANA CFS AWS, AS",-35.8,137.25,165.0,63.9
169 | 94872099999,"FERNY CREEK, AS",-37.8666666,145.3333333,561.0,67.7
170 | 94152099999,"BORROLOOLA, AS",-16.0833333,136.3,17.0,81.5
171 | 94754099999,"NULLO MOUNTAIN AWS, AS",-32.7333333,150.2333333,1130.0,52.3
172 | 95958099999,"SCOTTS PEAK DAM, AS",-43.05,146.2666666,408.0,60.6
173 | 94711099999,"COBAR MO, AS",-31.4833333,145.8333333,263.6,74.6
174 | 94749099999,"BELLAMBI AWS, AS",-34.3833333,150.9333333,10.0,64.3
175 | 95575099999,"BEAUDESERT DRUMLEY ST, AS",-27.9666666,152.9833333,48.0,75.2
176 | 94864099999,"MELBOURNE ESSENDON, AS",-37.728056,144.901944,85.95,70.1
177 | 94373099999,"YEPPOON THE ESPLANADE, AS",-23.1333333,150.75,6.0,79.5
178 | 94808099999,"NOARLUNGA, AS",-35.1666666,138.5,55.0,73.1
179 | 94317099999,"NEWMAN AERO, AS",-23.4166666,119.8,524.0,94.6
180 | 94212099999,"HALLS CREEK AIRPORT, AS",-18.2333333,127.6666666,424.0,88.6
181 | 95677099999,"ADELAIDE PARAFIELD, AS",-34.793333,138.633056,17.37,76.4
182 | 94703099999,"BOURKE AIRPORT AWS, AS",-30.0333333,145.95,108.0,76.2
183 | 94153099999,"GROOTE EYLANDT, AS",-13.975,136.46,16.15,79.8
184 | 94710099999,"COBAR AIRPORT AWS, AS",-31.5333333,145.8,218.0,74.8
185 | 94367099999,"MACKAY MO, AS",-21.1166666,149.2166666,33.0,78.7
186 | 95962099999,"WARRA, AS",-43.0666666,146.7,495.0,54.5
187 | 94865099999,"LAVERTON RAAF, AS",-37.8666666,144.75,20.0,72.9
188 | 94592099999,"GOLD COAST, AS",-28.164444,153.504722,6.4,74.7
189 | 94870099999,"MELBOURNE MOORABBIN, AS",-37.975833,145.102222,15.24,72.2
190 | 94975099999,"HOBART, AS",-42.836111,147.510278,3.96,60.3
191 | 94206099999,"FITZROY CROSSING AERO, AS",-18.1833333,125.5666666,115.0,90.7
192 | 94321099999,"WULUNGURRU, AS",-23.2666666,129.3666666,455.0,94.8
193 | 95458099999,"COOBER PEDY AIRPORT, AS",-29.0333333,134.7166666,226.0,88.5
194 | 94316099999,"PARABURDOO AERO, AS",-23.1666666,117.75,424.0,94.9
195 | 95956099999,"LUNCHERON HILL FORESTRY, AS",-41.15,145.15,340.0,58.7
196 | 94541099999,"INVERELL RESEARCH CENTRE, AS",-29.7833333,151.0833333,664.0,71.7
197 | 95678099999,"MOUNT LOFTY, AS",-34.9666666,138.7,730.0,69.2
198 | 94919099999,"KHANCOBAN, AS",-36.2333333,148.1333333,340.0,63.5
199 | 94814099999,"STRATHALBYN RACECOURSE, AS",-35.2833333,138.9,58.0,67.4
200 | 94651099999,"NULLARBOR, AS",-31.45,130.9,65.0,67.7
201 | 94809099999,"EDITHBURGH AWS, AS",-35.1166666,137.7333333,7.0,66.0
202 | 94866099999,"MELBOURNE INTERNATIONAL, AS",-37.673333,144.843333,132.28,73.8
203 | 94365099999,"PROSERPINE WHITSUNDAY COAST, AS",-20.495,148.552222,24.99,78.7
204 | 95642099999,"NORSEMAN AERO, AS",-32.2166666,121.75,263.0,74.4
205 | 94312099999,"PORT HEDLAND INTERNATIONAL, AS",-20.377778,118.626389,10.05,89.8
206 | 94617099999,"MANJIMUP, AS",-34.25,116.15,287.0,65.5
207 | 94234099999,"DALY WATERS AWS, AS",-16.25,133.3666666,211.0,87.5
208 | 95481099999,"MOOMBA AIRPORT, AS",-28.1,140.2,38.0,90.5
209 | 94840099999,"MORTLAKE RACECOURSE, AS",-38.0666666,142.7666666,131.0,69.1
210 | 94775099999,"TOCAL AWS, AS",-32.6333333,151.5833333,30.0,64.1
211 | 95323099999,"ARLTUNGA, AS",-23.4666666,134.6833333,664.0,91.9
212 | 94604099999,"BUNBURY, AS",-33.35,115.65,6.0,74.6
213 | 94274099999,"GEORGETOWN AIRPORT, AS",-18.3,143.5333333,302.0,76.5
214 | 95205099999,"DERBY AERO, AS",-17.3666666,123.6666666,7.0,88.6
215 | 95816099999,"ROBE AIRFIELD, AS",-37.1833333,139.8,4.0,66.2
216 | 94957099999,"OUSE FIRE STATION, AS",-42.4833333,146.7166666,91.0,60.5
217 | 94762099999,"HOLSWORTHY CONTROL RANGE, AS",-33.9833333,150.9166666,40.0,72.9
218 | 95706099999,"NARRANDERA, AS",-34.702222,146.512222,144.47,73.4
219 | 95974099999,"FINGAL LEGGE STREET, AS",-41.6333333,147.9666666,237.0,57.0
220 | 95896099999,"ALBURY AEROPORT, AS",-36.0666666,146.95,165.0,71.6
221 | 94684099999,"YUNTA AIRSTRIP, AS",-32.5666666,139.5666666,300.0,80.9
222 | 95572099999,"NAMBOUR DPI HILLSIDE, AS",-26.65,152.9333333,33.0,73.9
223 | 94839099999,"CHARLTON, AS",-36.2833333,143.35,132.0,75.8
224 | 94566099999,"GYMPIE, AS",-26.1833333,152.6333333,65.0,74.4
225 | 94338099999,"TREPELL AIRPORT, AS",-21.8333333,140.8833333,267.0,84.4
226 | 94255099999,"CAMOOWEAL TOWNSHIP, AS",-19.9166666,138.1166666,232.0,87.3
227 | 94821099999,"MOUNT GAMBIER AERO, AS",-37.7333333,140.7833333,69.0,73.4
228 | 95647099999,"NORTH WALPOLE, AS",-34.95,116.7166666,74.0,65.2
229 | 95687099999,"RENMARK AERO, AS",-34.2,140.6833333,32.0,82.2
230 | 94678099999,"MOUNT CRAWFORD AWS, AS",-34.7333333,138.9333333,525.0,72.0
231 | 94261099999,"CENTURY MINE, AS",-18.75,138.7,127.0,83.4
232 | 94898099999,"CERBERUS AWS, AS",-38.35,145.1666666,14.0,70.9
233 | 95634099999,"SOUTHERN CROSS AIRFIELD, AS",-31.2333333,119.35,348.0,80.1
234 | 95837099999,"RUTHERGLEN RESEARCH, AS",-36.1,146.5,175.0,70.9
235 | 94910099999,"WAGGA WAGGA, AS",-35.165278,147.466389,220.67,70.4
236 | 94239099999,"MCARTHUR RIVER MINE, AS",-16.4333333,136.0666666,41.0,81.5
237 | 95293099999,"WOOLSHED, AS",-19.4166666,146.5333333,559.0,73.7
238 | 94399099999,"LOCHINGTON, AS",-23.9333333,147.5166666,267.0,79.9
239 | 94609099999,"JANDAKOT AERO, AS",-32.1,115.8833333,31.0,79.8
240 | 94429099999,"MOUNT MAGNET AERO, AS",-28.1166666,117.8333333,408.0,89.4
241 | 95913099999,"MOUNT MOORNAPA, AS",-37.75,147.1333333,480.0,62.0
242 | 95663099999,"CUMMINS AERO, AS",-34.25,135.7166666,58.0,69.4
243 | 94631099999,"ROCKY GULLY, AS",-34.5666666,117.0166666,251.0,63.9
244 | 95773099999,"ARMIDALE AIRPORT AWS, AS",-30.5333333,151.6166666,1081.0,62.7
245 | 94874099999,"MANGALORE AIRPORT, AS",-36.8833333,145.1833333,141.0,68.9
246 | 95717099999,"PARKES AIRPORT, AS",-33.1333333,148.2333333,324.0,65.9
247 | 95835099999,"LONGERENONG, AS",-36.6666666,142.3,133.0,74.2
248 | 95570099999,"GRAFTON AIRPORT, AS",-29.75,153.0333333,26.0,72.4
249 | 94188099999,"CAPE FLATTERY, AS",-14.9666666,145.3166666,19.0,81.7
250 | 94598099999,"EVANS HEAD RAAF BOMBING RANGE, AS",-29.1833333,153.4,63.0,71.2
251 | 94610099999,"PERTH INTERNATIONAL, AS",-31.940278,115.966944,20.42,80.0
252 | 94276099999,"PALMERVILLE, AS",-16.0,144.0666666,205.0,79.2
253 | 94341099999,"RICHMOND, AS",-20.701944,143.114722,206.04,81.5
254 | 94555099999,"WARWICK, AS",-28.2,152.1,476.0,72.4
255 | 95671099999,"ROSEWORTHY AG COLLEGE, AS",-34.5166666,138.6833333,65.0,75.2
256 | 95832099999,"EDENHOPE AIRPORT, AS",-37.0166666,141.2666666,155.0,74.9
257 | 94915099999,"PERISHER VALLEY AWS, AS",-36.4,148.4,1735.0,48.2
258 | 95639099999,"SALMON GUMS RES. STATION, AS",-32.9833333,121.6166666,249.0,68.1
259 | 95754099999,"MERRIWA ROSCOMMON, AS",-32.1833333,150.1666666,376.0,61.5
260 | 95704099999,"GRIFFITH AIRPORT AWS, AS",-34.25,146.0666666,135.0,71.4
261 | 94938099999,"ULLADULLA AWS, AS",-35.35,150.4833333,37.0,65.6
262 | 95621099999,"COLLIE EAST, AS",-33.3666666,116.1666666,200.0,71.0
263 | 94690099999,"AUSTIN PLAINS, AS",-35.3777778,140.5377778,110.8,78.9
264 | 95448099999,"LEINSTER AERO, AS",-27.85,120.7,498.0,93.9
265 | 95636099999,"JACUP, AS",-33.8833333,119.1,306.0,62.6
266 | 94659099999,"WOOMERA, AS",-31.144167,136.816944,167.03,84.5
267 | 94306099999,"MARDIE, AS",-21.1833333,115.9666666,12.0,89.4
268 | 94268099999,"KOWANYAMA AIRPORT, AS",-15.4833333,141.75,11.0,79.0
269 | 95966099999,"LAUNCESTON AIRPORT, AS",-41.55,147.2166666,168.0,60.6
270 | 95918099999,"ORBOST, AS",-37.6833333,148.4666666,63.0,67.8
271 | 94746099999,"MOSS VALE AWS, AS",-34.5166666,150.4166666,679.0,56.3
272 | 95307099999,"KARRATHA AERO, AS",-20.7166666,116.7666666,6.0,89.5
273 | 94363099999,"EMERALD AIRPORT, AS",-23.5666666,148.1833333,190.0,80.4
274 | 94553099999,"APPLETHORPE, AS",-28.6166666,151.95,873.0,67.0
275 | 95529099999,"MILES CONSTANCE STREET, AS",-26.65,150.1833333,305.0,79.5
276 | 95840099999,"WESTMERE, AS",-37.7,142.9333333,227.0,70.4
277 | 94743099999,"MOUNT BOYCE, AS",-33.6166666,150.2666666,1080.0,51.0
278 | 94137099999,"JABIRU AIRPORT, AS",-12.6666666,132.9,28.0,81.0
279 | 94595899999,"TAREE, AS",-31.888611,152.513889,11.58,70.0
280 | 94906099999,"MOUNT HOTHAM, AS",-36.9666666,147.1333333,1849.0,49.4
281 | 94628099999,"NEWDEGATE RES. STATION, AS",-33.1166666,118.8333333,321.0,67.8
282 | 94143099999,"BULMAN AWS, AS",-13.6666666,134.3333333,105.0,76.9
283 | 94327099999,"JERVOIS, AS",-22.95,136.15,329.0,92.2
284 | 94855099999,"BENDIGO AIRPORT AWS, AS",-36.7333333,144.3166666,209.0,69.5
285 | 94612099999,"PEARCE, AS",-31.667778,116.015,45.41,81.0
286 | 95972099999,"CAMPANIA KINKORA, AS",-42.6833333,147.4166666,45.0,59.4
287 | 95719099999,"DUBBO AIRPORT AWS, AS",-32.2166666,148.5666666,285.0,66.4
288 | 95283099999,"COOKTOWN AIRPORT, AS",-15.45,145.1833333,6.0,80.6
289 | 94767099999,"SYDNEY INTERNATIONAL, AS",-33.946111,151.177222,6.4,66.8
290 | 94912099999,"BAIRNSDALE AIRPORT, AS",-37.8833333,147.5666666,50.0,64.3
291 | 95666099999,"PORT AUGUSTA ARID LANDS, AS",-32.5166666,137.7166666,14.0,81.0
292 | 94907099999,"EAST SALE, AS",-38.098889,147.149444,7.01,66.3
293 | 94802099999,"ALBANY AIRPORT, AS",-34.9414,117.8022,69.0,64.7
294 | 94959099999,"BUTLERS GORGE, AS",-42.2833333,146.2833333,667.0,55.7
295 | 94328099999,"TERRITORY GRAPE FARM, AS",-22.45,133.6333333,567.0,86.1
296 | 94987099999,"FRIENDLY BEACHES, AS",-42.0,148.2833333,56.0,60.1
297 | 94170099999,"WEIPA AERO, AS",-12.6833333,141.9166666,19.0,80.7
298 | 94576099999,"BRISBANE, AS",-27.4833333,153.0333333,8.0,76.1
299 | 95748099999,"WOLLONGONG AIRPORT, AS",-34.5666666,150.7833333,8.0,64.3
300 | 94686099999,"FOWLERS GAP AWS, AS",-31.0833333,141.7,182.0,81.8
301 | 94200099999,"MANDORA, AS",-19.7333333,120.85,8.0,89.3
302 | 95612099999,"GINGIN AERO, AS",-31.4666666,115.8666666,75.0,79.1
303 | 94335099999,"CLONCURRY AIRPORT, AS",-20.6666666,140.5,187.0,80.5
304 | 94896099999,"ALBURY, AS",-36.067778,146.958056,164.28,71.6
305 | 94836099999,"STAWELL AERODROME, AS",-37.0666666,142.7333333,235.0,72.4
306 | 94302099999,"LEARMONTH, AS",-22.235556,114.088611,5.79,89.3
307 | 94843099999,"SWAN HILL AERODROME, AS",-35.3833333,143.5333333,71.0,76.9
308 | 94682099999,"LOXTON RESEARCH CENTRE, AS",-34.4333333,140.6,30.0,81.1
309 | 94141099999,"CENTRAL ARNHEM PLATEAU, AS",-13.3333333,133.0833333,416.0,77.8
310 | 95977099999,"GROVE RESEARCH STATION, AS",-42.9833333,147.0666666,65.0,56.5
311 | 95937099999,"MORUYA AIRPORT, AS",-35.9,150.15,4.0,65.0
312 | 94850099999,"KING ISLAND AIRPORT, AS",-39.8833333,143.8833333,38.0,63.1
313 | 94785099999,"KEMPSEY AIRPORT AWS, AS",-31.0666666,152.7666666,14.0,71.1
314 | 94549099999,"KINGAROY AIRPORT, AS",-26.5666666,151.8333333,434.0,70.7
315 | 94873199999,"PUCKAPUNYAL LYON HILL DEFENCE, AS",-36.94,145.05,193.0,69.7
316 | 94569099999,"SUNSHINE COAST AIRPORT, AS",-26.6,153.1,4.0,78.1
317 | 94395099999,"CLERMONT AIRPORT, AS",-22.7833333,147.6166666,272.0,79.0
318 | 95931099999,"BEGA AWS, AS",-36.6666666,149.8166666,42.0,63.3
319 | 94895599999,"AVALON, AS",-38.039444,144.469444,10.66,70.4
320 | 95715099999,"WALGETT AIRPORT, AS",-30.0333333,148.1166666,134.0,77.0
321 | 95833099999,"KYABRAM INST SUSTAINABLE AG, AS",-36.3333333,145.0666666,104.0,69.1
322 | 94786099999,"PORT MACQUARIE AIRPORT AWS, AS",-31.4333333,152.85,5.0,72.1
323 | 95925099999,"MOUNT GININI, AS",-35.5333333,148.7666666,1760.0,46.1
324 | 94828099999,"PORTLAND CASHMORE AIRPORT, AS",-38.3166666,141.4666666,82.0,67.5
325 | 94225099999,"DELAMERE WEAPONS RANGE, AS",-15.75,131.9166666,222.0,86.6
326 | 94140099999,"MILINGIMBI AWS, AS",-12.1166666,134.9,16.0,79.5
327 | 95722099999,"TEMORA AIRPORT, AS",-34.4333333,147.5166666,281.0,69.1
328 | 95697099999,"IVANHOE AERODROME AWS, AS",-32.8833333,144.3166666,100.0,76.9
329 | 94608099999,"PERTH METRO, AS",-31.9166666,115.8666666,25.0,79.8
330 | 94510099999,"CHARLEVILLE, AS",-26.413334,146.2625,305.71,86.1
331 | 94517099999,"ST GEORGE AIRPORT, AS",-28.05,148.6,199.0,85.2
332 | 94835099999,"BEN NEVIS, AS",-37.2333333,143.2,875.0,64.5
333 | 95867099999,"SCORESBY RESEARCH INSTITUTE, AS",-37.8666666,145.25,80.0,72.5
334 | 94595199999,"AMBERLEY, AS",-27.640556,152.711944,27.73,76.3
335 | 94186099999,"LOCKHART RIVER AIRPORT, AS",-12.7833333,143.3,20.0,80.0
336 | 94231099999,"LAJAMANU, AS",-18.3333333,130.6333333,317.0,88.1
337 | 94387099999,"BUNDABERG AERO, AS",-24.9,152.3166666,28.0,75.8
338 | 94615099999,"GOOSEBERY HILL, AS",-31.95,116.05,220.0,77.7
339 | 95664099999,"WHYALLA, AS",-33.058889,137.514444,12.49,73.1
340 | 95827099999,"KANAGULK, AS",-37.1166666,141.8,189.0,74.6
341 | 94572099999,"LISMORE AIRPORT AWS, AS",-28.8333333,153.26,9.8,74.0
342 | 95611099999,"BUSSELTON AERO, AS",-33.6833333,115.4,17.0,72.4
343 | 94719099999,"DUBBO, AS",-32.216667,148.574722,284.98,66.2
344 | 94955099999,"SHEFFIELD SCHOOL FARM, AS",-41.3833333,146.3166666,295.0,59.3
345 | 94960099999,"TUNNAK FIRE STATION, AS",-42.45,147.4666666,462.0,52.9
346 | 95646099999,"FORREST, AS",-30.8333333,128.1166666,160.0,73.4
347 | 95936099999,"MELBOURNE OLYMPIC PARK, AS",-37.8333333,144.9833333,7.5,74.8
348 | 95866099999,"ESSENDON AIRPORT, AS",-37.7333333,144.9,79.0,74.8
349 | 94342099999,"WINTON AIRPORT, AS",-22.3666666,143.0833333,193.0,86.5
350 | 95716099999,"GOULBURN AIRPORT AWS, AS",-34.8166666,149.7333333,641.0,56.8
351 | 94614099999,"SWANBOURNE, AS",-31.95,115.7666666,41.0,76.2
352 | 94336099999,"THE MONUMENT AIRPORT, AS",-21.8,139.9166666,289.0,87.2
353 | 94232099999,"VICTORIA RIVER DOWNS, AS",-16.4,131.0166666,90.0,88.1
354 | 94683099999,"KUITPO FOREST RESERVE, AS",-35.1666666,138.6666666,365.0,67.8
355 | 94891099999,"LATROBE VALLEY AIRPORT, AS",-38.2166666,146.4666666,56.0,66.5
356 | 94238099999,"TENNANT CREEK AIRPORT, AS",-19.6333333,134.1833333,377.0,91.3
357 | 95658099999,"OLYMPIC DAM AERODROME, AS",-30.4833333,136.8833333,100.0,86.4
358 | 95710099999,"TRANGIE RESEARCH STATION, AS",-31.9833333,147.95,216.0,70.4
359 | 94829099999,"HAMILTON AIRPORT, AS",-37.65,142.0666666,242.0,71.3
360 | 95317099999,"MARBLE BAR, AS",-21.1833333,119.75,183.0,95.6
361 | 95485099999,"TIBOOBURRA, AS",-29.451111,142.057778,178.0,83.6
362 | 95815099999,"MUNKORA, AS",-36.1,140.3166666,28.0,74.6
363 | 94515099999,"ROMA AIRPORT, AS",-26.55,148.7833333,304.0,82.4
364 | 95825099999,"CASTERTON, AS",-37.5833333,141.3333333,131.0,74.6
365 | 94620099999,"DWELLINGUP, AS",-32.7166666,116.05,268.0,72.7
366 | 95822099999,"DARTMOOR, AS",-37.9166666,141.2666666,51.0,72.7
367 | 95767099999,"LAKE MACQUARIE AWS, AS",-33.0833333,151.4666666,6.0,65.4
368 | 94457099999,"WARBURTON AIRFIELD, AS",-26.1333333,126.5833333,460.0,93.9
369 | 95699099999,"WHITE CLIFFS AWS, AS",-30.85,143.07,158.0,80.7
370 | 94729099999,"BATHURST AIRPORT AWS, AS",-33.4166666,149.65,745.0,57.7
371 | 95929099999,"MERIMBULA AIRPORT, AS",-36.9166666,149.9,2.0,64.9
372 | 95543099999,"GAYNDAH AIRPORT, AS",-25.6166666,151.6166666,112.0,76.6
373 | 94346099999,"LONGREACH AERO, AS",-23.4333333,144.2833333,192.0,84.8
374 | 94791099999,"COFFS HARBOUR, AS",-30.3205556,153.1163889,5.0,72.5
375 | 95610099999,"KALAMUNDA BICKLEY, AS",-32.0166666,116.1333333,385.0,73.7
376 | 94288099999,"CAIRNS RACECOURSE, AS",-16.95,145.75,401.0,79.6
377 | 94343099999,"HUGHENDEN AIRPORT, AS",-20.8166666,144.2333333,316.0,80.8
378 | 95214099999,"WYNDHAM AERO, AS",-15.5,128.15,4.0,91.9
379 | 94130099999,"BRADSHAW, AS",-14.95,130.8,76.0,90.2
380 | 94681099999,"NURIOOTPA VITICULTURAL, AS",-34.4833333,139.0,276.0,75.5
381 | 95487099999,"BALLERA GAS FIELD, AS",-27.4166666,141.8166666,115.0,88.3
382 | 94838099999,"HOPETOUN AIRPORT, AS",-35.7166666,142.35,78.0,74.4
383 | 95765099999,"SYDNEY OLYMPIC PARK AWS ARCHERY CENTRE, AS",-33.8333333,151.0666666,4.0,65.8
384 | 94461099999,"GILES METEOROLOGICAL OFFICE, AS",-25.0333333,128.3,599.0,90.6
385 | 94183099999,"COEN AIRPORT, AS",-13.7666666,143.1166666,160.0,78.2
386 | 94396099999,"ROLLESTON AIRPORT, AS",-24.4666666,148.6333333,220.0,79.6
387 | 95771099999,"CESSNOCK AIRPORT, AS",-32.7833333,151.3333333,62.0,64.8
388 | 95654099999,"WUDINNA AERO, AS",-33.05,135.45,87.0,75.0
389 | 95709099999,"WEST WYALONG AIRPORT AWS, AS",-33.9333333,147.2,258.0,67.9
390 | 95551099999,"TOOWOOMBA AIRPORT, AS",-27.55,151.9166666,642.0,69.6
391 | 94344099999,"URANDANGI AERODROME, AS",-21.6,138.3666666,75.0,92.2
392 | 95874099999,"VIEWBANK ARPNSA, AS",-37.7333333,145.1,66.0,73.9
393 | 94837099999,"WARRNAMBOOL AIRPORT NDB, AS",-38.2833333,142.45,71.0,70.1
394 | 94449099999,"LAVERTON AERO, AS",-28.6166666,122.4166666,465.0,89.4
395 | 94397099999,"MORANBAH, AS",-22.057778,148.0775,234.69,79.1
396 | 94727099999,"MUDGEE AIRPORT AWS, AS",-32.5666666,149.6166666,472.0,62.8
397 | 94570099999,"TEWANTIN RSL PARK, AS",-26.3833333,153.0333333,7.0,77.2
398 | 95869099999,"DENILIQUIN AIRPORT AWS, AS",-35.5666666,144.95,95.0,73.2
399 | 94287099999,"CAIRNS INTERNATIONAL, AS",-16.885833,145.755278,3.04,79.5
400 | 95979099999,"MOUNT WELLINGTON, AS",-42.9,147.2333333,1260.5,44.0
401 | 94674099999,"PORT LINCOLN, AS",-34.605278,135.880278,10.97,66.1
402 | 95823099999,"PADTHAWAY SOUTH, AS",-36.65,140.5166666,35.0,76.1
403 | 95111099999,"PORT KEATS AIRPORT, AS",-14.25,129.5333333,29.0,87.3
404 | 94125099999,"BATCHELOR AERO, AS",-13.05,131.0166666,105.0,83.5
405 | 95818099999,"PALLAMANA AERODROME, AS",-35.0666666,139.2333333,46.0,70.3
406 | 95708099999,"CONDOBOLIN AIRPORT, AS",-33.0666666,147.2166666,194.0,71.2
407 | 94894099999,"MOUNT BULLER AWS, AS",-37.15,146.4333333,1707.0,51.3
408 | 95492099999,"THARGOMINDAH, AS",-27.986389,143.810833,131.97,82.9
409 | 94889099999,"WANGARATTA AERO, AS",-36.4166666,146.3,153.0,69.9
410 | 94403099999,"GERALDTON, AS",-28.796111,114.7075,36.88,75.4
411 |
--------------------------------------------------------------------------------
/examples/data/sample_data.gslib:
--------------------------------------------------------------------------------
1 | #
2 | 5
3 | x
4 | y
5 | z
6 | porosity
7 | impedance
8 | 51 12 6 0.315 8754.48
9 | 51 12 7 0.309 8545.85
10 | 51 12 8 0.304 8341.22
11 | 24 50 1 0.292 7752.68
12 | 24 50 2 0.283 7663.65
13 | 24 50 3 0.253779 7644.15
14 | 24 50 4 0.259107 7658.44
15 | 0 4 5 0.324 6394.14
16 | 0 4 6 0.306 6535.19
17 | 71 80 7 0.314581 8546.87
18 | 71 80 8 0.312 8561.47
19 | 40 11 3 0.281 9204.04
20 | 40 11 4 0.301 8962.13
21 | 40 11 7 0.304 8775.5
22 | 40 11 8 0.317 8557.07
23 | 40 11 9 0.272 8249.47
24 | 84 6 2 0.269 9254.27
25 | 84 6 3 0.319 8936.03
26 | 19 35 1 0.278 9042.8
27 | 19 35 2 0.286 9222.36
28 | 69 114 0 0.291 8710.99
29 | 69 114 2 0.315 8278.49
30 | 69 114 3 0.2566 8098.95
31 | 69 114 4 0.31 7940.24
32 | 69 114 5 0.268 7805.64
33 | 69 114 8 0.304 7608.57
34 | 69 114 9 0.302 7608.56
35 | 99 51 1 0.263 8840.69
36 | 99 51 2 0.255 8824.67
37 | 44 34 6 0.299 7693.43
38 | 44 34 7 0.287 7642.95
39 | 44 34 8 0.325 7597.87
40 | 44 34 9 0.294 7556.49
41 | 31 54 4 0.308 9470.45
42 | 31 54 5 0.275 9105.9
43 | 31 54 6 0.301 8741.91
44 | 51 9 6 0.322 8600.02
45 | 51 9 7 0.306 8744.51
46 | 51 9 8 0.3258 8882.39
47 | 94 115 1 0.245221 8845.37
48 | 94 115 2 0.287 8587.12
49 | 94 115 3 0.271 8338.7
50 | 94 115 4 0.314 8133.23
51 | 94 115 5 0.289 8007.09
52 | 3 37 2 0.288554 7639.31
53 | 3 37 3 0.285 7353.15
54 | 3 37 4 0.297 7255.95
55 | 3 37 5 0.353 7344.63
56 | 3 37 6 0.31 7591.03
57 | 32 101 5 0.284 9511.93
58 | 32 101 6 0.3 9187.27
59 | 32 101 7 0.291 8780.2
60 | 32 101 8 0.265 8352.78
61 | 32 101 9 0.317 7979.34
62 | 46 50 0 0.309 8300.39
63 | 46 50 2 0.249348 7927.25
64 | 46 50 3 0.304 7798.84
65 | 46 50 6 0.311 7598.79
66 | 46 50 7 0.286 7587.72
67 | 46 50 8 0.32 7590.56
68 | 46 50 9 0.304 7600.43
69 | 29 20 4 0.294 7979.03
70 | 29 20 5 0.293 7984.11
71 | 37 125 5 0.253 7440.66
72 | 37 125 6 0.297 7155.93
73 | 37 125 8 0.2196 6632.43
74 | 53 9 6 0.303 8542.37
75 | 53 9 7 0.309 8591.16
76 | 53 9 8 0.302 8641.07
77 | 35 93 4 0.299 7846.1
78 | 35 93 8 0.302 7319.58
79 | 35 93 9 0.302 7420.89
80 | 56 73 7 0.273 8148.86
81 | 56 73 8 0.3 8328.38
82 | 89 111 3 0.311062 7674.02
83 | 89 111 4 0.315 7547.67
84 | 89 111 5 0.282 7624.56
85 | 89 111 7 0.2689 8125.58
86 | 89 111 8 0.219 8384.55
87 | 72 39 8 0.281 8176.51
88 | 60 19 8 0.247353 8255.38
89 | 60 19 9 0.278498 8244.64
90 | 72 21 7 0.301 8126.25
91 | 48 116 0 0.31 10049.7
92 | 48 116 1 0.29 9900.57
93 | 48 116 7 0.281 9237.45
94 | 48 116 8 0.238 9216.65
95 | 36 36 0 0.299 7447.8
96 | 36 36 3 0.33 7080.18
97 | 36 36 4 0.245186 7017.52
98 | 36 36 5 0.274 7005.74
99 | 36 36 7 0.327 7039.45
100 | 36 36 8 0.305 7083.49
101 | 40 118 5 0.277 8636.83
102 | 40 118 6 0.303 8443.77
103 | 62 18 7 0.266696 8506.99
104 | 62 18 8 0.279174 8467.53
105 | 62 18 9 0.321009 8405.58
106 | 83 58 2 0.27 9086.49
107 | 83 58 3 0.256526 9211.44
108 | 83 58 4 0.29 9121.01
109 | 83 58 5 0.292 8861.71
110 | 98 61 3 0.31 8928.97
111 | 98 61 4 0.282 8803.22
112 | 98 61 6 0.287 8300.9
113 | 98 61 7 0.293 8181.74
114 | 98 61 8 0.295 8232.74
115 | 98 61 9 0.322 8416.4
116 | 44 122 0 0.314 9941.4
117 | 44 122 1 0.296 9905.26
118 | 44 122 6 0.313 9251.43
119 | 44 122 7 0.286 8936.84
120 | 44 122 8 0.267 8603.23
121 | 52 74 0 0.279 8572.27
122 | 52 74 1 0.302 8050.3
123 | 52 74 5 0.283 7255.43
124 | 52 74 7 0.291 7842.87
125 | 52 74 8 0.266 8253.02
126 | 62 32 0 0.31 9602.95
127 | 62 32 1 0.274 9485.01
128 | 45 115 0 0.298 9583.76
129 | 45 115 1 0.277 9495.1
130 | 45 115 7 0.289 8255.57
131 | 45 115 8 0.271 7917.43
132 | 38 65 0 0.319319 8453.76
133 | 38 65 1 0.252035 8134.39
134 | 38 65 2 0.27 8013.45
135 | 38 65 3 0.304 8052.85
136 | 38 65 6 0.295 8442.66
137 | 43 64 0 0.212 9506.34
138 | 43 64 1 0.29318 8988.82
139 | 92 22 1 0.265 8249.71
140 | 92 22 2 0.271 8306.45
141 | 92 22 3 0.293 8443.11
142 | 64 63 0 0.29 9277.46
143 | 51 79 0 0.271 7619.3
144 | 51 79 1 0.313 7428.38
145 | 51 79 2 0.267 7381.23
146 | 51 79 3 0.281 7483.69
147 | 62 87 5 0.264 8708.73
148 | 62 87 7 0.263 8484.8
149 | 62 87 8 0.324 8401.73
150 | 69 99 0 0.303 9125.36
151 | 69 99 1 0.299 8818.43
152 | 69 99 2 0.303 8541.81
153 | 69 99 7 0.267 8317.33
154 | 69 99 8 0.306 8583.93
155 | 37 87 4 0.304 8024.39
156 | 37 87 6 0.2567 8538.15
157 | 37 87 7 0.295 8637.14
158 | 37 87 8 0.287108 8517.08
159 | 37 87 9 0.2026 8168.67
160 | 80 108 4 0.314 8141.86
161 | 80 108 5 0.255 7925.11
162 | 80 108 6 0.223 7739.66
163 | 80 108 7 0.269 7644.8
164 | 80 108 8 0.281 7685.65
165 | 88 34 6 0.279 8374.12
166 | 88 34 7 0.23 8246.31
167 | 92 129 1 0.27 4784.17
168 | 92 129 2 0.28 4661.2
169 | 76 101 0 0.325 8320.91
170 | 76 101 4 0.327 8341.63
171 | 76 101 5 0.278 8298.95
172 | 76 101 7 0.272 8179.66
173 | 76 101 8 0.295 8110.41
174 | 54 127 8 0.304 4932.44
175 | 54 127 9 0.295 4659.97
176 | 55 11 7 0.323 8131.05
177 | 55 11 8 0.281 8139.31
178 | 20 111 5 0.287 8107.66
179 | 20 111 6 0.255 8016.58
180 | 20 111 7 0.291 7922.29
181 | 45 58 0 0.297 8943.3
182 | 45 58 1 0.272 8729.51
183 | 45 58 7 0.301 8013.96
184 | 45 58 8 0.305 7888.32
185 | 98 3 6 0.292 6034.04
186 | 98 3 7 0.315 6125.48
187 | 31 90 4 0.307 7767.38
188 | 31 90 5 0.2876 7708.25
189 | 31 90 6 0.282 7717.98
190 | 31 90 7 0.275 7826.09
191 | 31 90 8 0.274 8009.18
192 | 31 90 9 0.304 8245.58
193 | 16 16 3 0.272 9192.96
194 | 16 16 4 0.303 8819.69
195 | 16 16 6 0.294 8091.67
196 | 16 16 7 0.263 7820.5
197 | 16 16 8 0.293 7619.38
198 | 16 16 9 0.253 7497.54
199 | 39 87 6 0.285 8108.54
200 | 39 87 7 0.288 8299.14
201 | 39 87 8 0.263216 8447.09
202 | 39 87 9 0.2026 8474.82
203 | 9 25 1 0.248 8071.26
204 | 9 25 2 0.203 7910.3
205 | 9 25 3 0.261 7933.56
206 | 9 25 4 0.285 8101.5
207 | 9 25 6 0.3148 8494.28
208 | 9 25 7 0.240445 8607.51
209 | 68 116 0 0.298 9909.26
210 | 68 116 2 0.305 9611.1
211 | 68 116 3 0.286 9418.14
212 | 68 116 4 0.304 9212.23
213 | 68 116 5 0.268 8981.18
214 | 68 116 8 0.292 8279.81
215 | 68 116 9 0.29 8070.15
216 | 20 27 0 0.322 9138.23
217 | 20 27 6 0.280293 7673.04
218 | 20 27 7 0.287 7401.26
219 | 20 27 8 0.297 7212.3
220 | 20 27 9 0.285 7124.67
221 | 79 60 4 0.283 8783.73
222 | 79 60 5 0.297 8786.5
223 | 81 67 1 0.28 8184.15
224 | 81 67 2 0.286 8028.3
225 | 81 67 3 0.277 7927.88
226 | 84 81 1 0.264 9299.64
227 | 84 81 2 0.289 9364.56
228 | 84 81 3 0.252 9363.72
229 | 84 81 4 0.292 9263.49
230 | 84 81 6 0.266 8994.36
231 | 84 81 7 0.244 8927.14
232 | 84 81 9 0.315 9129.29
233 | 59 0 7 0.303 4275.54
234 | 59 0 8 0.297 4496.21
235 | 59 0 9 0.275 4835.24
236 | 52 68 0 0.282 8824.15
237 | 52 68 1 0.287 8486.62
238 | 52 68 6 0.272 7449.72
239 | 52 68 7 0.282 7486.73
240 | 52 68 8 0.271 7628.17
241 | 75 20 8 0.291 8316.43
242 | 68 3 8 0.283 5830.63
243 | 41 120 5 0.28 9068.96
244 | 41 120 6 0.299 8839.04
245 | 41 120 7 0.274 8583.58
246 | 41 120 8 0.287 8307.24
247 | 68 80 4 0.29 8675.53
248 | 68 80 5 0.298 8550.27
249 | 68 80 7 0.286739 8501.28
250 | 68 80 8 0.316 8554.87
251 | 84 109 4 0.317 7835.52
252 | 84 109 5 0.286 7812.89
253 | 84 109 7 0.268 8018.91
254 | 84 109 8 0.315416 8084.39
255 | 30 1 0 0.321 5035.61
256 | 30 1 1 0.261 4928.21
257 | 30 1 5 0.303 4969.39
258 | 30 1 7 0.294 5085.23
259 | 30 1 8 0.287 5143.28
260 | 30 1 9 0.309 5192.35
261 | 86 34 4 0.296 8468.2
262 | 86 34 5 0.28 8428.54
263 | 86 34 8 0.307 8263.97
264 | 86 34 9 0.305 8181.37
265 | 90 55 3 0.292 8478.72
266 | 90 55 4 0.286 8640.83
267 | 90 55 7 0.272 8368.76
268 | 90 55 8 0.281 8146.43
269 | 60 122 4 0.326 9369.36
270 | 60 122 5 0.291 9316.12
271 | 60 122 8 0.297 9066.02
272 | 60 122 9 0.307 8960.28
273 | 78 122 7 0.29 8564.21
274 | 78 122 8 0.283 8268.05
275 | 67 28 2 0.3 8871.32
276 | 67 28 3 0.266 8892.45
277 | 67 28 4 0.302 8951.12
278 | 10 31 1 0.291 9198.68
279 | 10 31 2 0.234014 8544.04
280 | 10 31 3 0.295 8081.45
281 | 10 31 4 0.269 7896.86
282 | 74 32 2 0.278 8007.92
283 | 74 32 3 0.282 7942.71
284 | 74 32 4 0.317 7916.4
285 | 74 32 7 0.298 8072.34
286 | 74 32 9 0.285 8191.75
287 | 0 96 1 0.265 9182.96
288 | 0 96 2 0.223 8978.56
289 | 0 96 5 0.313 8492.07
290 | 0 96 6 0.301 8402.85
291 | 74 115 0 0.345 9668.26
292 | 5 41 3 0.274 7287.93
293 | 5 41 4 0.277 7432.05
294 | 5 41 5 0.345 7673.74
295 | 5 41 6 0.307 7990.15
296 | 51 95 2 0.279 8744.21
297 | 51 95 3 0.312 8662.82
298 | 64 25 3 0.279 9397.96
299 | 64 25 4 0.287 9428.83
300 | 41 83 2 0.266 8132.49
301 | 41 83 3 0.276 8362.61
302 | 41 83 6 0.276 8603.27
303 | 41 83 7 0.285 8378.15
304 | 41 83 8 0.240802 8028.98
305 | 41 83 9 0.29394 7720.26
306 | 24 77 4 0.303 8729.31
307 | 24 77 7 0.29 9358.84
308 | 24 77 8 0.291 9146.72
309 | 24 77 9 0.305 8875.01
310 | 53 22 3 0.33 8586.03
311 | 53 22 4 0.281 8681.85
312 | 70 49 7 0.272 8345.86
313 | 70 49 8 0.29 8370.46
314 | 80 33 4 0.296 7994.96
315 | 80 33 5 0.305 8012.07
316 | 80 33 8 0.29 8337.05
317 | 80 33 9 0.281 8412.34
318 | 33 19 0 0.279 8982.54
319 | 33 19 1 0.288 8867.19
320 | 42 97 1 0.271 9343.83
321 | 42 97 3 0.297 9309.97
322 | 42 97 4 0.278 9291.72
323 | 42 97 6 0.3 9239.12
324 | 42 97 7 0.223 9179.86
325 | 42 97 8 0.305 9096.01
326 | 42 97 9 0.28 8980.67
327 | 70 85 7 0.231311 8626.31
328 | 70 85 8 0.311 8545.81
329 | 64 69 0 0.297 8375.26
330 | 80 89 1 0.297 9307.26
331 | 80 89 2 0.296 9174.17
332 | 80 89 3 0.262 9061.66
333 | 80 89 4 0.316 8892.72
334 | 80 89 8 0.288 8572.61
335 | 80 89 9 0.315 8688.37
336 | 61 37 0 0.307 8678.04
337 | 61 37 1 0.271 8521.73
338 | 36 28 3 0.302018 8940.49
339 | 36 28 4 0.240181 8869.73
340 | 36 28 5 0.278 8754.33
341 | 36 28 6 0.275 8606.94
342 | 36 28 7 0.287 8431.85
343 | 36 28 8 0.314 8223.01
344 | 3 124 1 0.269 8070.23
345 | 3 124 2 0.28 7585.63
346 | 3 124 3 0.324 7131.06
347 | 3 124 4 0.305 6817.26
348 | 18 28 0 0.308 9531.78
349 | 18 28 6 0.296 8417.17
350 | 18 28 7 0.296 7992.24
351 | 18 28 8 0.291 7666.12
352 | 18 28 9 0.277 7470.16
353 | 50 33 8 0.335 8042.93
354 | 50 33 9 0.295 7911.72
355 | 62 120 3 0.29 8854.06
356 | 62 120 4 0.314 8734.75
357 | 62 120 5 0.294 8611.35
358 | 62 120 8 0.285 8249.84
359 | 62 120 9 0.296 8136.65
360 | 20 19 0 0.311 8593.74
361 | 20 19 7 0.285 8554.47
362 | 62 35 0 0.311 8401.93
363 | 62 35 1 0.269 8311.08
364 | 32 118 6 0.284 8908.73
365 | 32 118 7 0.268 8850.56
366 | 35 110 5 0.2362 7933.57
367 | 35 110 6 0.295 7627.01
368 | 38 72 2 0.276 9116.65
369 | 38 72 3 0.302 8602.78
370 | 38 72 4 0.285 8266.71
371 | 38 72 5 0.272 8103.28
372 | 38 72 6 0.287 8088.67
373 | 38 72 8 0.267 8315.48
374 | 38 72 9 0.306 8496.93
375 | 98 59 1 0.278295 9279.01
376 | 98 59 2 0.263 8975.14
377 | 98 59 6 0.308 8922.35
378 | 98 59 7 0.287 8929.4
379 | 98 59 8 0.29 8637.96
380 | 98 59 9 0.329 8277.96
381 | 90 5 1 0.264 7961.78
382 | 90 5 2 0.255 7836.32
383 | 62 118 3 0.277 7955.32
384 | 62 118 4 0.294 7861.18
385 | 62 118 8 0.282 7663.57
386 | 62 118 9 0.288 7652.07
387 | 45 27 3 0.307 8643.22
388 | 45 27 4 0.296 8587.31
389 | 45 27 6 0.314 8658.52
390 | 45 27 7 0.304 8725.84
391 | 45 27 8 0.307 8777.91
392 | 45 27 9 0.28 8737.11
393 | 66 129 0 0.255436 4109.09
394 | 66 129 2 0.29 4020.74
395 | 66 129 3 0.272 3991.85
396 | 28 31 0 0.322 10089.9
397 | 28 31 7 0.31 7623.15
398 | 28 31 8 0.294 7369.93
399 | 28 31 9 0.273 7212.74
400 | 56 109 4 0.317 9658.38
401 | 56 109 8 0.299 9137.98
402 | 56 109 9 0.272 9037.13
403 | 51 101 0 0.294 9001.21
404 | 51 101 1 0.3 9086.22
405 | 51 101 8 0.233 9150.64
406 | 51 101 9 0.277 9012.86
407 | 60 19 8 0.29767 8255.38
408 | 60 19 9 0.319678 8244.64
409 | 28 121 5 0.28 8866.5
410 | 28 121 6 0.269 8750.33
411 | 28 121 7 0.279 8640.09
412 | 96 73 3 0.305 8647.23
413 | 96 73 4 0.273 8545.8
414 | 37 22 3 0.30599 8874.36
415 | 37 22 4 0.302029 8708.47
416 | 37 22 8 0.292 8282.58
417 | 37 22 9 0.298 8246.35
418 | 67 84 7 0.2522 8911.96
419 | 67 84 8 0.328 8951.28
420 | 23 47 1 0.262 9456.46
421 | 23 47 2 0.29 9414.33
422 | 23 47 7 0.29 7972.46
423 | 23 47 8 0.3 7757.01
424 | 23 47 9 0.279 7668.3
425 | 11 22 3 0.29 9104.48
426 | 11 22 4 0.271 8546.92
427 | 11 22 8 0.320762 7909.42
428 | 11 22 9 0.254 8138.57
429 | 28 44 1 0.322861 10082.2
430 | 28 44 2 0.2882 9474.45
431 | 28 44 5 0.268 8038.91
432 | 28 44 6 0.282 7748.93
433 | 28 44 7 0.3 7521.73
434 | 28 44 8 0.335 7340.23
435 | 28 44 9 0.299 7207
436 | 25 111 8 0.267766 7742.8
437 | 25 111 9 0.287 7588.25
438 | 11 86 6 0.303 9125.45
439 | 11 86 7 0.291 9019.7
440 | 64 61 0 0.273 9278.74
441 | 25 124 7 0.3 7560.25
442 | 99 118 1 0.26 8247.16
443 | 99 118 2 0.279 8114.22
444 | 99 118 3 0.276 8021.14
445 | 99 118 5 0.295 7988.47
446 | 99 118 6 0.319976 8028.86
447 | 99 118 7 0.262 8132.78
448 | 99 118 8 0.29 8253.17
449 | 99 118 9 0.3 8399.69
450 | 44 71 0 0.307888 8704.94
451 | 44 71 1 0.262425 8608.31
452 | 44 71 5 0.249423 7081.28
453 | 44 71 8 0.268 8672.05
454 | 44 71 9 0.316 9242.09
455 | 18 81 6 0.284 8844.8
456 | 18 81 7 0.3215 9026.47
457 | 30 120 4 0.308 9112.49
458 | 30 120 5 0.269 9064.29
459 | 30 120 6 0.282 9023.02
460 | 21 47 2 0.297 9102.39
461 | 21 47 8 0.307 7659.54
462 | 21 47 9 0.277 7556.62
463 | 87 22 2 0.233 8086.85
464 | 87 22 3 0.3 8002.55
465 | 40 106 7 0.27 8800.24
466 | 7 44 3 0.283 7451.31
467 | 7 44 4 0.285 7751.16
468 | 7 44 5 0.348 8154.19
469 | 7 44 6 0.301 8564.7
470 | 6 8 1 0.238 7857.01
471 | 6 8 3 0.255 7852.87
472 | 6 8 5 0.343 7884.17
473 | 6 8 6 0.286 7921.92
474 | 72 37 8 0.273 8026.72
475 | 69 74 4 0.283 8472.04
476 | 69 74 5 0.292 8481.62
477 | 88 37 4 0.2173 8179.23
478 | 88 37 5 0.265 7998.72
479 | 38 7 3 0.268 8558.02
480 | 38 7 4 0.326 8361.62
481 | 7 33 2 0.329555 7711.75
482 | 7 33 3 0.271 7885.03
483 | 7 33 4 0.29 8086.22
484 | 7 33 5 0.3537 8261.22
485 | 7 33 6 0.302 8379.26
486 | 52 110 0 0.281 8995.84
487 | 52 110 1 0.297 8970.69
488 | 52 110 3 0.312 9024.45
489 | 52 110 4 0.309 9079.29
490 | 52 110 7 0.265 9175.94
491 | 52 110 8 0.257 9119.89
492 | 63 121 3 0.279 7730.89
493 | 63 121 4 0.284 7737.66
494 | 63 121 5 0.294 7755.02
495 | 63 121 7 0.292 7867.93
496 | 63 121 8 0.3 7939.89
497 | 63 121 9 0.284 8009.09
498 | 83 10 2 0.271 8122.64
499 | 83 10 3 0.304 7580.92
500 | 47 50 1 0.301 7827.74
501 | 47 50 2 0.277 7734.37
502 | 47 50 3 0.303 7676.34
503 | 47 50 7 0.287 7551.77
504 | 47 50 8 0.308 7549.4
505 | 47 50 9 0.303 7551.22
506 | 40 56 2 0.24613 8266.91
507 | 40 56 3 0.313 8316.92
508 | 40 56 4 0.269 8349.25
509 | 25 82 3 0.29 9026.75
510 | 25 82 4 0.295 9221.46
511 | 50 129 6 0.306 3574.93
512 | 50 129 7 0.267 3437.91
513 | 77 4 5 0.287 7327.83
514 | 77 4 7 0.300803 7366.2
515 | 77 4 8 0.264 7298.16
516 | 32 118 6 0.284 8908.73
517 | 32 118 7 0.268 8850.56
518 | 69 60 0 0.294 8878.74
519 | 87 49 2 0.294 8529.37
520 | 87 49 3 0.278 8343.51
521 | 87 49 4 0.274 8293.27
522 | 87 49 5 0.2436 8386.41
523 | 87 49 7 0.273 8719.26
524 | 87 49 8 0.313 8789.96
525 | 85 95 6 0.269 7892.83
526 | 85 95 7 0.266 7954.7
527 | 99 22 2 0.268 9535.61
528 | 99 22 3 0.29 9552.95
529 | 99 22 8 0.303 8625.21
530 | 65 3 7 0.296 5840.84
531 | 65 3 8 0.286 5917.67
532 | 64 54 8 0.298 8312.09
533 | 42 56 2 0.206 8830.54
534 | 42 56 3 0.295 8559.09
535 | 42 56 4 0.27 8351
536 | 74 43 7 0.274 8940.05
537 | 74 43 8 0.266 8735.63
538 | 59 128 0 0.280152 5629.12
539 | 59 128 3 0.277 5232.28
540 | 59 128 4 0.304 5071.82
541 | 59 128 5 0.277 4903.77
542 | 59 128 8 0.296 4431.72
543 | 59 128 9 0.326 4306.03
544 | 86 47 3 0.278 9110.71
545 | 86 47 4 0.272 8889.78
546 | 86 47 5 0.275 8701.11
547 | 86 47 7 0.258 8530.71
548 | 86 47 8 0.32 8565.19
549 | 87 46 3 0.279 8845.98
550 | 87 46 4 0.287 8620.39
551 | 87 46 5 0.252 8483
552 | 87 46 7 0.261 8516.72
553 | 87 46 8 0.3191 8605.51
554 | 2 107 1 0.255 7885.89
555 | 2 107 2 0.247 7861.84
556 | 2 107 3 0.306 8042.91
557 | 2 107 4 0.297 8321.82
558 | 13 86 6 0.295 9177.9
559 | 13 86 7 0.304 9117.85
560 | 38 42 0 0.314 7939.35
561 | 38 42 2 0.255 7536.33
562 | 38 42 3 0.308 7393.58
563 | 38 42 4 0.28 7346.58
564 | 38 42 6 0.301 7347.4
565 | 38 42 7 0.326 7393.86
566 | 38 42 8 0.316 7476.39
567 | 38 42 9 0.32363 7558.92
568 | 54 81 0 0.301632 8609.49
569 | 54 81 4 0.240519 8167.01
570 | 54 81 5 0.25092 8152.33
571 |
--------------------------------------------------------------------------------
/examples/data/tatitlek_815_mhhw_2011.nc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/czwchenzhun/tfinterpy/9dc3b97260ec8b1d9d6631c33c3e19c298bb6f4a/examples/data/tatitlek_815_mhhw_2011.nc
--------------------------------------------------------------------------------
/examples/gui/guiDemo.py:
--------------------------------------------------------------------------------
1 | from tfinterpy.gui.tool import *
2 |
3 | if __name__ == '__main__':
4 | app = QApplication(sys.argv)
5 | exe = Tool()
6 | exe.showMaximized()
7 | sys.exit(app.exec_())
8 |
--------------------------------------------------------------------------------
/examples/ncFileUtil.py:
--------------------------------------------------------------------------------
1 | import netCDF4 as nc
2 | import random
3 | import numpy as np
4 | import os
5 | import os.path as op
6 |
7 |
8 | def getNCFileList(dirPath):
9 | '''
10 | Returns all netcdf files' path under the specified directory.
11 |
12 | :param dirPath: str, directory.
13 | :return: list, files' path.
14 | '''
15 | ls = []
16 | if not op.exists(dirPath):
17 | return ls
18 | for file in os.listdir(dirPath):
19 | if file[-3:] == '.nc':
20 | ls.append(file)
21 | return ls
22 |
23 |
24 | def peakNCWH(filePath, wk="lon", hk="lat"):
25 | '''
26 | Get the width and height information contained in the nc file.
27 |
28 | :param filePath: str.
29 | :param wk: str, the key corresponding to the width.
30 | :param hk: str, the key corresponding to the height.
31 | :return: tuple, (width, height).
32 | If the file does not contain width and height information,
33 | return (None,None).
34 | '''
35 | if not op.exists(filePath):
36 | return None, None
37 | try:
38 | dem = nc.Dataset(filePath)
39 | except:
40 | print("netcdf 文件读取异常")
41 | return None, None
42 | W = dem.dimensions[wk].size
43 | H = dem.dimensions[hk].size
44 | dem.close()
45 | return W, H
46 |
47 |
48 | def peakNCInfo(filePath):
49 | '''
50 | Get the key and corresponding shape information contained in the nc file.
51 |
52 | :param filePath: str.
53 | :return: tuple, (keys,info).
54 | keys is list containing all key in nc file.
55 | info is a string that records the shape of the variables.
56 | '''
57 | if not op.exists(filePath):
58 | return None, None
59 | try:
60 | dem = nc.Dataset(filePath)
61 | except:
62 | print("netcdf 文件读取异常")
63 | return None, None
64 | info = ''
65 | keys = []
66 | for key in dem.variables.keys():
67 | if dem.variables[key].shape == ():
68 | continue
69 | keys.append(key)
70 | info += "%s shape: %s\n" % (key, str(dem.variables[key].shape))
71 | dem.close()
72 | return keys, info
73 |
74 |
75 | def getSamples(filePathOrData, X, Y, Z, begin=(0, 0), sub=(200, 200), N=10):
76 | '''
77 | :param filePath: str.
78 | :param X: str, key of lats.
79 | :param Y: str, key of lons.
80 | :param Z: str, key of ele.
81 | :param begin: tuple, the begining index of the submap.
82 | :param sub: tuple, the size of the submap.
83 | :param N: integer, number of samples in X and Y directions.
84 | :return: tuple, (samples,lats,lons,ele).
85 | samples is the sampling point obtained by random sampling within the submap.
86 | lats is latitude of submap.
87 | lons is longitude of submap.
88 | ele is elevation of submap.
89 | '''
90 | if type(filePathOrData) == type(''):
91 | dem = nc.Dataset(filePathOrData)
92 | data = dem.variables
93 | else:
94 | data = filePathOrData
95 | by, bx = begin
96 | suby, subx = sub
97 | lats = data[X][bx:bx + subx] # 纬度值
98 | lons = data[Y][by:by + suby] # 经度值
99 | ele = data[Z][bx:bx + subx, by:by + suby] # 海拔值
100 | if type(filePathOrData) == type(''):
101 | dem.close() #
102 | subx, suby = sub
103 | samples = []
104 | c = 0
105 | while c < N:
106 | x = random.randint(0, subx - 1)
107 | y = random.randint(0, suby - 1)
108 | if [x, y, ele[y, x]] not in samples:
109 | samples.append([x, y, ele[y, x]])
110 | c += 1
111 | samples = np.array(samples, dtype="float32")
112 | return samples, lats, lons, ele
113 |
--------------------------------------------------------------------------------
/examples/nestVariogram.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 | from tfinterpy.variogram import calculateOmnidirectionalVariogram2D
3 | from ncFileUtil import getSamples
4 | from tfinterpy.utils import calcVecs
5 |
6 | if __name__ == "__main__":
7 | filePath = "data/tatitlek_815_mhhw_2011.nc"
8 | W, H = 200, 200
9 | M = 100
10 | offset = (100, 100)
11 |
12 | # Get sample points and original elevation data from netcdf file
13 | # containing Digital Elevation Model data.
14 | samples, lats, lons, ele = getSamples(filePath, 'lat', 'lon', 'Band1', offset, (W, H), M)
15 |
16 | # Calculate the nested variogram function.
17 | nestVariogram, variogramBuilders = calculateOmnidirectionalVariogram2D(samples)
18 | for vb in variogramBuilders:
19 | plt.figure()
20 | vb.showVariogram()
21 | plt.show()
22 |
--------------------------------------------------------------------------------
/examples/plotUtils.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 |
3 | plt.rcParams['font.sans-serif'] = ['SimHei']
4 | plt.rcParams['axes.unicode_minus'] = False
5 |
6 |
7 | def img2d(data, xlabel="lons", ylabel="lats", title="", vmin=None, vmax=None):
8 | '''
9 | Plotting 2d data as image.
10 |
11 | :param data: ndarray, 2d data.
12 | :param xlabel: str.
13 | :param ylabel: str.
14 | :param title: str.
15 | :param vmin: number.
16 | :param vmax: number.
17 | :return: None.
18 | '''
19 | if title != "":
20 | plt.title(title)
21 | plt.imshow(data, cmap="rainbow", vmin=vmin, vmax=vmax)
22 | ax = plt.gca()
23 | ax.set_xlabel(xlabel)
24 | ax.get_xaxis().get_major_formatter().set_scientific(False)
25 | ax.set_ylabel(ylabel)
26 | ax.get_yaxis().get_major_formatter().set_scientific(False)
27 | plt.colorbar()
28 |
29 |
30 | def scatter2d(data, xidx=0, yidx=1, zidx=-1, axes=None, xlabel="lons", ylabel="lats", title=""):
31 | '''
32 | Plotting 2d scatter.
33 |
34 | :param data: ndarray, points data.
35 | :param xidx: integer, index of x coordinate.
36 | :param yidx: integer, index of y coordinate.
37 | :param zidx: integer, index of property.
38 | :param axes: matplotlib axes.
39 | :param xlabel: str.
40 | :param ylabel: str.
41 | :param title: str.
42 | :return: matplotlib.collections.PathCollection object.
43 | '''
44 | if title != "":
45 | plt.title(title)
46 | if axes is None:
47 | if zidx >= 0:
48 | scatter = plt.scatter(data[:, xidx], data[:, yidx], s=data[:, zidx], alpha=0.5)
49 | else:
50 | scatter = plt.scatter(data[:, xidx], data[:, yidx], alpha=0.5)
51 | else:
52 | if zidx >= 0:
53 | scatter = axes.scatter(data[:, xidx], data[:, yidx], s=data[:, zidx], alpha=0.5)
54 | else:
55 | scatter = axes.scatter(data[:, xidx], data[:, yidx], alpha=0.5)
56 | ax = plt.gca()
57 | ax.set_xlabel(xlabel)
58 | ax.get_xaxis().get_major_formatter().set_scientific(False)
59 | ax.set_ylabel(ylabel)
60 | ax.get_yaxis().get_major_formatter().set_scientific(False)
61 | return scatter
62 |
63 |
64 | def scatter3d(data, axes=None, xlabel='h', ylabel='angle', zlabel='var', alpha=0.5, title=""):
65 | '''
66 | Plotting 3d scatter.
67 |
68 | :param data: ndarray, points data.
69 | :param axes: matplotlib axes.
70 | :param xlabel: str.
71 | :param ylabel: str.
72 | :param zlabel: str.
73 | :param alpha: number.
74 | :param title: str.
75 | :return: matplotlib.axes._subplots.Axes3DSubplot object.
76 | '''
77 | if title != "":
78 | plt.title(title)
79 | if axes is None:
80 | axes = plt.axes(projection='3d')
81 | X, Y, Z = data[:, 0], data[:, 1], data[:, 2]
82 | scatter = axes.scatter(X, Y, Z, alpha=alpha)
83 | axes.set_xlabel(xlabel)
84 | axes.set_ylabel(ylabel)
85 | axes.set_zlabel(zlabel)
86 | return scatter
87 |
--------------------------------------------------------------------------------
/examples/temperature.py:
--------------------------------------------------------------------------------
1 | from tfinterpy.krige import OK
2 | from plotUtils import *
3 | from tfinterpy.variogram import calculateOmnidirectionalVariogram2D
4 | from tfinterpy.utils import calcVecs
5 | import pandas as pd
6 |
7 | if __name__ == '__main__':
8 | df = pd.read_csv("data/AustraliaTemperature20210101.csv")
9 | samples = df[["LONGITUDE", "LATITUDE", "TEMP"]].values
10 |
11 | nv, vbs = calculateOmnidirectionalVariogram2D(samples, model=None)
12 | for vb in vbs:
13 | plt.figure()
14 | vb.showVariogram()
15 | plt.show()
16 | N = 8
17 | exe = OK(samples)
18 | print(exe.crossValidate(N, nv))
19 | print(exe.crossValidateKFold(10, N, nv))
20 |
--------------------------------------------------------------------------------
/examples/tf/IDW2D.py:
--------------------------------------------------------------------------------
1 | from tfinterpy.tf.idw import TFIDW
2 | from tfinterpy.grid import Grid2D
3 | from ncFileUtil import getSamples
4 | from plotUtils import *
5 | import numpy as np
6 | import tensorflow as tf
7 | import random
8 |
9 | if __name__ == "__main__":
10 | print(tf.config.experimental.list_physical_devices('CPU')) # Prints all CPU devices.
11 | print(tf.config.experimental.list_physical_devices('GPU')) # Prints all GPU devices.
12 |
13 | random.seed(1)
14 | W, H = 100, 100
15 | M = 100
16 | offset = (400, 800)
17 | N = 8
18 |
19 | # Get sample points and original elevation data from netcdf file
20 | # containing Digital Elevation Model data.
21 | samples, lats, lons, ele = getSamples("data/tatitlek_815_mhhw_2011.nc", 'lat', 'lon', 'Band1',
22 | offset, (W, H), M)
23 | # Create linear 2D grid.
24 | grid = Grid2D()
25 | grid.rectlinear((W, H), (1, W), (1, H))
26 |
27 | exe = TFIDW(samples)# Create a idw(tensorflow version) interpolator.
28 |
29 | # Specify the GPU to be used.
30 | with tf.device("/GPU:0"):
31 | # Perform interpolation of all points in the grid.
32 | grid.pro = exe.execute(grid.points(), N)
33 |
34 | print(exe.crossValidate(N))# Perform leave-one-out validation and print result.
35 | print(exe.crossValidateKFold(10, N))# Perform k-fold validation and print result.
36 |
37 | pro = grid.pro.reshape((grid.dim[1], grid.dim[0]))# Reshape properties as 2d ndarray.
38 | plt.figure()
39 | plt.subplot(221)
40 | img2d(ele, title="origin")# Plotting original elevation data.
41 | plt.subplot(222)
42 | img2d(pro, title="estimate")# Plotting interpolation results.
43 | absdiff = np.abs(pro - ele)
44 | plt.subplot(223)
45 | img2d(absdiff, title="error")# Plotting absolute errors.
46 | print('result MAE:', np.mean(absdiff))
47 | plt.show()
48 |
--------------------------------------------------------------------------------
/examples/tf/IDW3D.py:
--------------------------------------------------------------------------------
1 | import tfinterpy.vtk.colorMap as CM
2 | from tfinterpy.vtk.rendering import createGridActor, rendering
3 | from tfinterpy.vtk.fileUtils import saveVTKGrid
4 | from tfinterpy.tf.idw import TFIDW
5 | from tfinterpy.grid import Grid3D
6 | from tfinterpy.gslib.fileUtils import readGslibPoints
7 | import tensorflow as tf
8 |
9 | if __name__ == "__main__":
10 | print(tf.config.experimental.list_physical_devices('CPU')) # Prints all CPU devices.
11 | print(tf.config.experimental.list_physical_devices('GPU')) # Prints all GPU devices.
12 |
13 | filePath = "data/sample_data.gslib"
14 | N = 8
15 | df = readGslibPoints(filePath)# Read 3d points from gslib file.
16 | print(df.describe())
17 | samples = df[['x', 'y', 'z', 'porosity']].values
18 |
19 | # Create linear 3D grid.
20 | grid = Grid3D()
21 | grid.rectlinear((100, 100, 10), (samples[:, 0].min(), samples[:, 0].max()),
22 | (samples[:, 1].min(), samples[:, 1].max()), (samples[:, 2].min(), samples[:, 2].max()))
23 | exe = TFIDW(samples, '3d')# Create a idw interpolator.
24 |
25 | # Specify the GPU to be used.
26 | with tf.device("/GPU:0"):
27 | # Perform interpolation of all points in the grid.
28 | grid.pro = exe.execute(grid.points(), N)
29 |
30 | print(exe.crossValidate(N))# Perform leave-one-out validation and print result.
31 | print(exe.crossValidateKFold(10, N))# Perform k-fold validation and print result.
32 |
33 | # Create an actor representing a rectilinear grid and use the interpolation results for color mapping.
34 | actor = createGridActor(*grid.dim, grid.x, grid.y, grid.z, grid.pro,
35 | [samples[:, 3].min(), samples[:, 3].max()], CM.Rainbow)
36 | rendering(actor)# Rendering vtkActor.
37 | saveVTKGrid('savedData/grid.vtk', actor.GetMapper().GetInput())# Save grid data to vtk file.
38 |
--------------------------------------------------------------------------------
/examples/tf/OK2D.py:
--------------------------------------------------------------------------------
1 | from tfinterpy.tf.krige import TFOK
2 | from tfinterpy.grid import Grid2D
3 | import tensorflow as tf
4 | from ncFileUtil import getSamples
5 | from plotUtils import *
6 | import numpy as np
7 | from tfinterpy.variogram import calculateDefaultVariogram2D
8 | from tfinterpy.tf.variogramLayer import getVariogramLayer
9 | import random
10 |
11 | if __name__ == "__main__":
12 | print(tf.config.experimental.list_physical_devices('CPU')) # Prints all CPU devices.
13 | print(tf.config.experimental.list_physical_devices('GPU')) # Prints all GPU devices.
14 |
15 | random.seed(1)
16 | W, H = 200, 200
17 | M = 100
18 | offset = (100, 300)
19 | N = 8
20 |
21 | # Get sample points and original elevation data from netcdf file
22 | # containing Digital Elevation Model data.
23 | samples, lats, lons, ele = getSamples("data/tatitlek_815_mhhw_2011.nc", 'lat', 'lon', 'Band1',
24 | offset, (W, H), M)
25 |
26 | # Create linear 2D grid.
27 | grid = Grid2D()
28 | grid.rectlinear((W, H), (1, W), (1, H))
29 |
30 | # Calculate a default variogram function.
31 | vb = calculateDefaultVariogram2D(samples)
32 | plt.figure()
33 | vb.showVariogram()
34 | plt.show()
35 | vl = getVariogramLayer(vb)#Create variogram layer by variogram builder.
36 |
37 | exe = TFOK(samples)# Create a ok(tensorflow version) interpolator.
38 |
39 | # Specify the GPU to be used.
40 | with tf.device("/GPU:0"):
41 | # Perform interpolation of all points in the grid.
42 | grid.pro, grid.sigma = exe.execute(grid.points(), N, vl, 1000)
43 |
44 | print(exe.crossValidateKFold(10, N, vl))# Perform k-fold validation and print result.
45 | print(exe.crossValidate(N, vl))# Perform leave-one-out validation and print result.
46 |
47 | pro = grid.pro.reshape((grid.dim[1], grid.dim[0]))# Reshape properties as 2d ndarray.
48 | sigma = grid.sigma.reshape((grid.dim[1], grid.dim[0]))# Reshape kriging variances as 2d ndarray.
49 | plt.figure(figsize=(8, 8))
50 | plt.subplot(221)
51 | img2d(ele, title="origin")# Plotting original elevation data.
52 | plt.subplot(222)
53 | img2d(pro, title="estimate")# Plotting interpolation results.
54 | absdiff = np.abs(pro - ele)
55 | plt.subplot(223)
56 | img2d(absdiff, title="error")# Plotting absolute errors.
57 | print('result MAE:', np.mean(absdiff))
58 | plt.subplot(224)
59 | img2d(sigma, title="krige variance")# Plotting kriging variances.
60 | plt.show()
61 |
--------------------------------------------------------------------------------
/examples/tf/OK2DWithNestVariogram.py:
--------------------------------------------------------------------------------
1 | from tfinterpy.tf.krige import TFOK
2 | from tfinterpy.grid import Grid2D
3 | import tensorflow as tf
4 | from ncFileUtil import getSamples
5 | from plotUtils import *
6 | import numpy as np
7 | from tfinterpy.utils import calcVecs
8 | from tfinterpy.variogram import calculateOmnidirectionalVariogram2D
9 | from tfinterpy.tf.variogramLayer import getNestVariogramLayer
10 | import random
11 |
12 | if __name__ == "__main__":
13 | print(tf.config.experimental.list_physical_devices('CPU')) # Prints all CPU devices.
14 | print(tf.config.experimental.list_physical_devices('GPU')) # Prints all GPU devices.
15 |
16 | random.seed(1)
17 | W, H = 200, 200
18 | M = 100
19 | offset = (200, 0)
20 | N = 8
21 |
22 | # Get sample points and original elevation data from netcdf file
23 | # containing Digital Elevation Model data.
24 | samples, lats, lons, ele = getSamples("data/tatitlek_815_mhhw_2011.nc", 'lat', 'lon', 'Band1',
25 | offset, (W, H), M)
26 |
27 | # Create linear 2D grid.
28 | grid = Grid2D()
29 | grid.rectlinear((W, H), (1, W), (1, H))
30 |
31 | # Calculate nested variation function.
32 | nestVariogram, variogramBuilders = calculateOmnidirectionalVariogram2D(samples)
33 | # Get nested variation function layer.
34 | nestVariogramLayer = getNestVariogramLayer(variogramBuilders, nestVariogram.unitVectors)
35 |
36 | exe = TFOK(samples)# Create a ok(tensorflow version) interpolator.
37 |
38 | # Specify the GPU to be used.
39 | with tf.device("/GPU:0"):
40 | # Perform interpolation of all points in the grid.
41 | grid.pro, grid.sigma = exe.execute(grid.points(), N, nestVariogramLayer, 10000)
42 |
43 | print(exe.crossValidateKFold(10, N, nestVariogramLayer))# Perform k-fold validation and print result.
44 | print(exe.crossValidate(N, nestVariogramLayer))# Perform leave-one-out validation and print result.
45 |
46 | pro = grid.pro.reshape((grid.dim[1], grid.dim[0]))# Reshape properties as 2d ndarray.
47 | sigma = grid.sigma.reshape((grid.dim[1], grid.dim[0]))# Reshape kriging variances as 2d ndarray.
48 | plt.figure(figsize=(8, 8))
49 | plt.subplot(221)
50 | img2d(ele, title="origin")# Plotting original elevation data.
51 | plt.subplot(222)
52 | img2d(pro, title="estimate")# Plotting interpolation results.
53 | absdiff = np.abs(pro - ele)
54 | plt.subplot(223)
55 | img2d(absdiff, title="error")# Plotting absolute errors.
56 | print('result MAE:', np.mean(absdiff))
57 | plt.subplot(224)
58 | img2d(sigma, title="krige variance")# Plotting kriging variances.
59 | plt.show()
60 |
--------------------------------------------------------------------------------
/examples/tf/OK3D.py:
--------------------------------------------------------------------------------
1 | from tfinterpy.variogram import calculateDefaultVariogram3D
2 | from tfinterpy.gslib.fileUtils import readGslibPoints
3 | from tfinterpy.vtk.rendering import createGridActor, rendering
4 | import tfinterpy.vtk.colorMap as CM
5 | from tfinterpy.vtk.fileUtils import saveVTKGrid
6 | # import vtk dependencies first
7 | from tfinterpy.tf.variogramLayer import getVariogramLayer
8 | from tfinterpy.tf.krige import TFOK
9 | from tfinterpy.grid import Grid3D
10 | import matplotlib.pyplot as plt
11 | import tensorflow as tf
12 |
13 | if __name__ == "__main__":
14 | print(tf.config.experimental.list_physical_devices('CPU')) # Prints all CPU devices.
15 | print(tf.config.experimental.list_physical_devices('GPU')) # Prints all GPU devices.
16 |
17 | filePath = "data/sample_data.gslib"
18 | N = 8
19 | df = readGslibPoints(filePath)# Read 3d points from gslib file.
20 | print(df.describe())
21 | samples = df[['x', 'y', 'z', 'porosity']].values
22 |
23 | # Create linear 3D grid.
24 | grid = Grid3D()
25 | grid.rectlinear((100, 100, 10), (samples[:, 0].min(), samples[:, 0].max()),
26 | (samples[:, 1].min(), samples[:, 1].max()), (samples[:, 2].min(), samples[:, 2].max()))
27 |
28 | # Calculate a default variogram function.
29 | vb = calculateDefaultVariogram3D(samples)
30 | plt.figure()
31 | vb.showVariogram()
32 | plt.show()
33 | vl = getVariogramLayer(vb)#Create variogram layer by variogram builder.
34 |
35 | exe = TFOK(samples, '3d')# Create a ok(tensorflow version) interpolator.
36 |
37 | # Specify the GPU to be used.
38 | with tf.device("/GPU:0"):
39 | # Perform interpolation of all points in the grid.
40 | grid.pro, grid.sigma = exe.execute(grid.points(), N, vl, 1000)
41 |
42 | # Create an actor representing a rectilinear grid and use the interpolation results for color mapping.
43 | actor = createGridActor(*grid.dim, grid.x, grid.y, grid.z, grid.pro,
44 | [samples[:, 3].min(), samples[:, 3].max()], CM.Rainbow)
45 | rendering(actor)# Rendering vtkActor.
46 | # Create an actor representing a rectilinear grid and use the kriging variances for color mapping.
47 | actor = createGridActor(*grid.dim, grid.x, grid.y, grid.z, grid.sigma, None, CM.Rainbow)
48 | rendering(actor)# Rendering vtkActor.
49 | saveVTKGrid('savedData/grid.vtk', actor.GetMapper().GetInput())# Save grid data(kriging variances) to vtk file.
50 |
--------------------------------------------------------------------------------
/examples/tf/OK3DWithNestVariogram.py:
--------------------------------------------------------------------------------
1 | from tfinterpy.variogram import calculateOmnidirectionalVariogram3D
2 | from tfinterpy.gslib.fileUtils import readGslibPoints
3 | from tfinterpy.vtk.rendering import createGridActor, rendering
4 | import tfinterpy.vtk.colorMap as CM
5 | from tfinterpy.vtk.fileUtils import saveVTKGrid
6 | # import vtk dependencies first
7 | from tfinterpy.tf.variogramLayer import getNestVariogramLayer
8 | from tfinterpy.tf.krige import TFOK
9 | from tfinterpy.grid import Grid3D
10 | from tfinterpy.utils import calcVecs
11 | import matplotlib.pyplot as plt
12 | import tensorflow as tf
13 |
14 |
15 | if __name__ == "__main__":
16 | print(tf.config.experimental.list_physical_devices('CPU')) # Prints all CPU devices.
17 | print(tf.config.experimental.list_physical_devices('GPU')) # Prints all GPU devices.
18 |
19 | filePath = "data/sample_data.gslib"
20 | N = 8
21 | df = readGslibPoints(filePath)# Read 3d points from gslib file.
22 | print(df.describe())
23 | samples = df[['x', 'y', 'z', 'porosity']].values
24 |
25 | # Create linear 3D grid.
26 | grid = Grid3D()
27 | grid.rectlinear((100, 100, 10), (samples[:, 0].min(), samples[:, 0].max()),
28 | (samples[:, 1].min(), samples[:, 1].max()), (samples[:, 2].min(), samples[:, 2].max()))
29 |
30 | # Calculate nested variation function.
31 | nestVariogram, variogramBuilders = calculateOmnidirectionalVariogram3D(samples, [5, 5])
32 | for vb in variogramBuilders:
33 | plt.figure()
34 | vb.showVariogram()
35 | plt.show()
36 | # Get nested variation function layer.
37 | vl = getNestVariogramLayer(variogramBuilders, nestVariogram.unitVectors)
38 |
39 | exe = TFOK(samples, '3d')# Create a ok(tensorflow version) interpolator.
40 | # Specify the GPU to be used.
41 | with tf.device("/CPU:0"):
42 | # Perform interpolation of all points in the grid.
43 | grid.pro, grid.sigma = exe.execute(grid.points(), N, vl, batch_size=10000)
44 |
45 | print(exe.crossValidateKFold(10, N, vl))# Perform k-fold validation and print result.
46 | print(exe.crossValidate(N, vl))# Perform leave-one-out validation and print result.
47 |
48 | # Create an actor representing a rectilinear grid and use the interpolation results for color mapping.
49 | actor = createGridActor(*grid.dim, grid.x, grid.y, grid.z, grid.pro, [samples[:, 3].min(), samples[:, 3].max()],
50 | CM.Rainbow)
51 | rendering(actor)# Rendering vtkActor.
52 | # Create an actor representing a rectilinear grid and use the kriging variances for color mapping.
53 | actor = createGridActor(*grid.dim, grid.x, grid.y, grid.z, grid.sigma, None, CM.Rainbow)
54 | rendering(actor)# Rendering vtkActor.
55 | saveVTKGrid('savedData/grid.vtk', actor.GetMapper().GetInput())# Save grid data(kriging variances) to vtk file.
56 |
--------------------------------------------------------------------------------
/examples/tf/SK2D.py:
--------------------------------------------------------------------------------
1 | from tfinterpy.tf.krige import TFSK
2 | from tfinterpy.grid import Grid2D
3 | from ncFileUtil import getSamples
4 | from plotUtils import *
5 | import numpy as np
6 | import tensorflow as tf
7 | from tfinterpy.variogram import calculateDefaultVariogram2D
8 | from tfinterpy.tf.variogramLayer import getVariogramLayer
9 | import random
10 |
11 | if __name__ == "__main__":
12 | print(tf.config.experimental.list_physical_devices('CPU')) # Prints all CPU devices.
13 | print(tf.config.experimental.list_physical_devices('GPU')) # Prints all GPU devices.
14 |
15 | random.seed(1)
16 | W, H = 100, 100
17 | M = 100
18 | offset = (400, 800)
19 | N = 8
20 |
21 | # Get sample points and original elevation data from netcdf file
22 | # containing Digital Elevation Model data.
23 | samples, lats, lons, ele = getSamples("data/tatitlek_815_mhhw_2011.nc", 'lat', 'lon', 'Band1',
24 | offset, (W, H), M)
25 |
26 | # Create linear 2D grid.
27 | grid = Grid2D()
28 | grid.rectlinear((W, H), (1, W), (1, H))
29 |
30 | # Calculate a default variogram function.
31 | vb = calculateDefaultVariogram2D(samples)
32 | plt.figure()
33 | vb.showVariogram()
34 | plt.show()
35 | vl = getVariogramLayer(vb)#Create variogram layer by variogram builder.
36 |
37 | exe = TFSK(samples)# Create a sk(tensorflow version) interpolator.
38 |
39 | # Specify the GPU to be used.
40 | with tf.device("/GPU:0"):
41 | # Perform interpolation of all points in the grid.
42 | grid.pro, grid.sigma = exe.execute(grid.points(), N, vl, 1000)
43 |
44 | print(exe.crossValidateKFold(10, N, vl))# Perform k-fold validation and print result.
45 | print(exe.crossValidate(N, vl))# Perform leave-one-out validation and print result.
46 |
47 | pro = grid.pro.reshape((grid.dim[1], grid.dim[0]))# Reshape properties as 2d ndarray.
48 | sigma = grid.sigma.reshape((grid.dim[1], grid.dim[0]))# Reshape kriging variances as 2d ndarray.
49 | plt.figure(figsize=(8, 8))
50 | plt.subplot(221)
51 | img2d(ele, title="origin")# Plotting original elevation data.
52 | plt.subplot(222)
53 | img2d(pro, title="estimate")# Plotting interpolation results.
54 | absdiff = np.abs(pro - ele)
55 | plt.subplot(223)
56 | img2d(absdiff, title="error")# Plotting absolute errors.
57 | print('result MAE:', np.mean(absdiff))
58 | plt.subplot(224)
59 | img2d(sigma, title="krige variance")# Plotting kriging variances.
60 | plt.show()
61 |
--------------------------------------------------------------------------------
/examples/tf/SK2DWithNestVariogram.py:
--------------------------------------------------------------------------------
1 | from tfinterpy.tf.krige import TFSK
2 | from tfinterpy.grid import Grid2D
3 | from ncFileUtil import getSamples
4 | from plotUtils import *
5 | import numpy as np
6 | import tensorflow as tf
7 | from tfinterpy.utils import calcVecs
8 | from tfinterpy.variogram import calculateOmnidirectionalVariogram2D
9 | from tfinterpy.tf.variogramLayer import getNestVariogramLayer
10 | import random
11 |
12 | if __name__ == "__main__":
13 | print(tf.config.experimental.list_physical_devices('CPU')) # Prints all CPU devices.
14 | print(tf.config.experimental.list_physical_devices('GPU')) # Prints all GPU devices.
15 |
16 | random.seed(1)
17 | W, H = 100, 100
18 | M = 100
19 | offset = (400, 800)
20 | N = 8
21 |
22 | # Get sample points and original elevation data from netcdf file
23 | # containing Digital Elevation Model data.
24 | samples, lats, lons, ele = getSamples("data/tatitlek_815_mhhw_2011.nc", 'lat', 'lon', 'Band1',
25 | offset, (W, H), M)
26 |
27 | # Create linear 2D grid.
28 | grid = Grid2D()
29 | grid.rectlinear((W, H), (1, W), (1, H))
30 |
31 | # Calculate nested variation function.
32 | nestVariogram, variogramBuilders = calculateOmnidirectionalVariogram2D(samples)
33 | # Get nested variation function layer.
34 | nestVariogramLayer = getNestVariogramLayer(variogramBuilders, nestVariogram.unitVectors)
35 |
36 | exe = TFSK(samples)# Create a sk(tensorflow version) interpolator
37 |
38 | # Specify the GPU to be used.
39 | with tf.device("/GPU:0"):
40 | # Perform interpolation of all points in the grid.
41 | grid.pro, grid.sigma = exe.execute(grid.points(), N, nestVariogramLayer, 1000)
42 |
43 | print(exe.crossValidateKFold(10, N, nestVariogramLayer))# Perform k-fold validation and print result.
44 | print(exe.crossValidate(N, nestVariogramLayer))# Perform leave-one-out validation and print result.
45 |
46 | pro = grid.pro.reshape((grid.dim[1], grid.dim[0]))# Reshape properties as 2d ndarray.
47 | sigma = grid.sigma.reshape((grid.dim[1], grid.dim[0]))# Reshape kriging variances as 2d ndarray.
48 | plt.figure(figsize=(8, 8))
49 | plt.subplot(221)
50 | img2d(ele, title="origin")# Plotting original elevation data.
51 | plt.subplot(222)
52 | img2d(pro, title="estimate")# Plotting interpolation results.
53 | absdiff = np.abs(pro - ele)
54 | plt.subplot(223)
55 | img2d(absdiff, title="error")# Plotting absolute errors.
56 | print('result MAE:', np.mean(absdiff))
57 | plt.subplot(224)
58 | img2d(sigma, title="krige variance")# Plotting kriging variances.
59 | plt.show()
60 |
--------------------------------------------------------------------------------
/examples/tf/SK3D.py:
--------------------------------------------------------------------------------
1 | from tfinterpy.variogram import calculateDefaultVariogram3D
2 | from tfinterpy.gslib.fileUtils import readGslibPoints
3 | from tfinterpy.vtk.rendering import createGridActor, rendering
4 | import tfinterpy.vtk.colorMap as CM
5 | from tfinterpy.vtk.fileUtils import saveVTKGrid
6 | # import vtk dependencies first
7 | from tfinterpy.tf.variogramLayer import getVariogramLayer
8 | from tfinterpy.tf.krige import TFSK
9 | from tfinterpy.grid import Grid3D
10 | import matplotlib.pyplot as plt
11 | import tensorflow as tf
12 |
13 | if __name__ == "__main__":
14 | print(tf.config.experimental.list_physical_devices('CPU')) # Prints all CPU devices.
15 | print(tf.config.experimental.list_physical_devices('GPU')) # Prints all GPU devices.
16 |
17 | filePath = "data/sample_data.gslib"
18 | N = 8
19 | df = readGslibPoints(filePath)# Read 3d points from gslib file.
20 | print(df.describe())
21 | samples = df[['x', 'y', 'z', 'porosity']].values
22 |
23 | # Create linear 3D grid.
24 | grid = Grid3D()
25 | grid.rectlinear((100, 100, 10), (samples[:, 0].min(), samples[:, 0].max()),
26 | (samples[:, 1].min(), samples[:, 1].max()), (samples[:, 2].min(), samples[:, 2].max()))
27 |
28 | # Calculate a default variogram function.
29 | vb = calculateDefaultVariogram3D(samples)
30 | plt.figure()
31 | vb.showVariogram()
32 | plt.show()
33 | vl = getVariogramLayer(vb)#Create variogram layer by variogram builder.
34 |
35 | exe = TFSK(samples, '3d')# Create a sk(tensorflow version) interpolator.
36 |
37 | # Specify the GPU to be used.
38 | with tf.device("/GPU:0"):
39 | # Perform interpolation of all points in the grid.
40 | grid.pro, grid.sigma = exe.execute(grid.points(), N, vl, 1000)
41 |
42 | print(exe.crossValidateKFold(10, N, vl))# Perform leave-one-out validation and print result.
43 | print(exe.crossValidate(N, vl))# Perform k-fold validation and print result.
44 |
45 | # Create an actor representing a rectilinear grid and use the interpolation results for color mapping.
46 | actor = createGridActor(*grid.dim, grid.x, grid.y, grid.z, grid.pro, [samples[:, 3].min(), samples[:, 3].max()],
47 | CM.Rainbow)
48 | rendering(actor)# Rendering vtkActor.
49 | # Create an actor representing a rectilinear grid and use the kriging variances for color mapping.
50 | actor = createGridActor(*grid.dim, grid.x, grid.y, grid.z, grid.sigma, None, CM.Rainbow)
51 | rendering(actor)# Rendering vtkActor.
52 | saveVTKGrid('savedData/grid.vtk', actor.GetMapper().GetInput())# Save grid data(kriging variances) to vtk file.
53 |
--------------------------------------------------------------------------------
/examples/tf/SK3DWithNestVariogram.py:
--------------------------------------------------------------------------------
1 | from tfinterpy.variogram import calculateOmnidirectionalVariogram3D
2 | from tfinterpy.gslib.fileUtils import readGslibPoints
3 | import tfinterpy.vtk.colorMap as CM
4 | from tfinterpy.vtk.rendering import createGridActor, rendering
5 | from tfinterpy.vtk.fileUtils import saveVTKGrid
6 | # import vtk dependencies first
7 | from tfinterpy.tf.variogramLayer import getNestVariogramLayer
8 | from tfinterpy.tf.krige import TFSK
9 | from tfinterpy.grid import Grid3D
10 | from tfinterpy.utils import calcVecs
11 | import matplotlib.pyplot as plt
12 | import tensorflow as tf
13 |
14 |
15 | if __name__ == "__main__":
16 | print(tf.config.experimental.list_physical_devices('CPU')) # Prints all CPU devices.
17 | print(tf.config.experimental.list_physical_devices('GPU')) # Prints all GPU devices.
18 |
19 | filePath = "data/sample_data.gslib"
20 | N = 8
21 | df = readGslibPoints(filePath)# Read 3d points from gslib file.
22 | print(df.describe())
23 | samples = df[['x', 'y', 'z', 'porosity']].values
24 |
25 | # Create linear 3D grid.
26 | grid = Grid3D()
27 | grid.rectlinear((100, 100, 10), (samples[:, 0].min(), samples[:, 0].max()),
28 | (samples[:, 1].min(), samples[:, 1].max()), (samples[:, 2].min(), samples[:, 2].max()))
29 |
30 | # Calculate nested variation function.
31 | nestVariogram, variogramBuilders = calculateOmnidirectionalVariogram3D(samples, [5, 5])
32 | for vb in variogramBuilders:
33 | plt.figure()
34 | vb.showVariogram()
35 | plt.show()
36 | # Get nested variation function layer.
37 | vl = getNestVariogramLayer(variogramBuilders, nestVariogram.unitVectors)
38 |
39 | exe = TFSK(samples, '3d')# Create a sk(tensorflow version) interpolator.
40 | # Specify the GPU to be used.
41 | with tf.device("/GPU:0"):
42 | # Perform interpolation of all points in the grid.
43 | grid.pro, grid.sigma = exe.execute(grid.points(), N, vl, 10000)
44 |
45 | print(exe.crossValidateKFold(10, N, vl))# Perform k-fold validation and print result.
46 | print(exe.crossValidate(N, vl))# Perform leave-one-out validation and print result.
47 |
48 | # Create an actor representing a rectilinear grid and use the interpolation results for color mapping.
49 | actor = createGridActor(*grid.dim, grid.x, grid.y, grid.z, grid.pro, [samples[:, 3].min(), samples[:, 3].max()],
50 | CM.Rainbow)
51 | rendering(actor)# Rendering vtkActor.
52 | # Create an actor representing a rectilinear grid and use the kriging variances for color mapping.
53 | actor = createGridActor(*grid.dim, grid.x, grid.y, grid.z, grid.sigma, None, CM.Rainbow)
54 | rendering(actor)# Rendering vtkActor.
55 | saveVTKGrid('savedData/grid.vtk', actor.GetMapper().GetInput())# Save grid data(kriging variances) to vtk file.
56 |
57 |
--------------------------------------------------------------------------------
/examples/variogram.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 | from tfinterpy.variogram import VariogramBuilder
3 | from tfinterpy.variogramExp import search2d
4 | from ncFileUtil import getSamples
5 | from tfinterpy.utils import calcVecs, calcHAVByVecs
6 | import numpy as np
7 |
8 | if __name__ == "__main__":
9 | filePath = "data/tatitlek_815_mhhw_2011.nc"
10 | W, H = 200, 200
11 | M = 100
12 | offset = (100, 100)
13 |
14 | # Get sample points and original elevation data from netcdf file
15 | # containing Digital Elevation Model data.
16 | samples, lats, lons, ele = getSamples(filePath, 'lat', 'lon', 'Band1', offset, (W, H), M)
17 | vecs = calcVecs(samples, repeat=False)# Calculate the vectors between sampling points.
18 | hav = calcHAVByVecs(vecs)# Calculate distance, angle, semivariance by vectors.
19 | lagNum = 20
20 | lag = hav[:, 0].max() / 2 / lagNum
21 | lagTole = lag * 0.5
22 | angles = hav[:, 1]
23 | buckets = []
24 | portionNum = 8
25 | portion = np.pi / portionNum
26 | for i in range(portionNum):
27 | count = np.where((angles > portion * i) & (angles < portion * (i + 1)))[0].shape[0]
28 | buckets.append(count)
29 | idx = np.argmax(buckets)
30 | angle = portion * idx
31 | angleTole = portion
32 | bandWidth = hav[:, 0].mean() / 10
33 | #Search for lags
34 | lags, _ = search2d(vecs[:, :2], hav[:, 2], lagNum, lag, lagTole, angle, angleTole, bandWidth)
35 | vb = VariogramBuilder(lags)# Create a VariogramBuilder object.
36 | plt.figure()
37 | vb.showVariogram()# Plot variogram function.
38 | plt.show()
39 |
--------------------------------------------------------------------------------
/figs/OK3D.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/czwchenzhun/tfinterpy/9dc3b97260ec8b1d9d6631c33c3e19c298bb6f4a/figs/OK3D.jpg
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | matplotlib==3.9.4
2 | numpy==2.0.2
3 | pandas==2.2.3
4 | PyQt5==5.15.11
5 | scipy==1.13.1
6 | tensorflow==2.18.0
7 | tensorflow-gpu==2.18.0
8 | vtk==9.4.1
--------------------------------------------------------------------------------
/src/tfinterpy/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/czwchenzhun/tfinterpy/9dc3b97260ec8b1d9d6631c33c3e19c298bb6f4a/src/tfinterpy/__init__.py
--------------------------------------------------------------------------------
/src/tfinterpy/grid.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 |
3 |
4 | class Grid2D:
5 | '''
6 | Classes used to represent a two-dimensional grid.
7 | '''
8 |
9 | def __init__(self):
10 | self.x = None
11 | self.y = None
12 | self.xran = None
13 | self.yran = None
14 | self._xy = None
15 | self.dim = [-1, -1] #width and height
16 |
17 | def rectlinear(self, dim, xran, yran):
18 | '''
19 | Initialize the two-dimensional grid according to the dimension, x range, y range.
20 |
21 | :param dim: array_like, array containing two integer. [width, height].
22 | :param xran: array_like, [xbegin, xend]. So the step of x is equal to (xend-xbegin)/(width-1).
23 | :param yran: array_like, [ybegin, yend].
24 | :return: None
25 | '''
26 | self.dim = dim
27 | self.xran = xran
28 | self.yran = yran
29 | xstep = (xran[1] - xran[0]) / (dim[0] - 1)
30 | self.x = np.array([(i * xstep + xran[0]) for i in range(dim[0])])
31 | ystep = (yran[1] - yran[0]) / (dim[1] - 1)
32 | self.y = np.array([(i * ystep + yran[0]) for i in range(dim[1])])
33 | self._xy = None
34 |
35 | def setXCoords(self, xcoords):
36 | '''
37 | Sets the x coordinate of the grid.
38 |
39 | :param xcoords: array_like, array containing all the coordinates along the x axis.
40 | :return: None
41 | '''
42 | self.x = np.array(xcoords)
43 | self.dim[0] = len(self.x)
44 | self.xran = [self.x.min(), self.x.max()]
45 | self._xy = None
46 |
47 | def setYCoords(self, ycoords):
48 | '''
49 | Sets the y coordinate of the grid.
50 |
51 | :param ycoords: array_like, array containing all the coordinates along the y axis.
52 | :return: None
53 | '''
54 | self.y = np.array(ycoords)
55 | self.dim[1] = len(self.y)
56 | self.yran = [self.y.min(), self.y.max()]
57 | self._xy = None
58 |
59 | def points(self):
60 | '''
61 | Returns an ndarray containing all coordinates on the grid,
62 | and the shape of the array is (width*height, 2).
63 |
64 | :return: ndarray
65 | '''
66 | if self._xy is None:
67 | self._xy = np.zeros((self.dim[1], self.dim[0], 2))
68 | for i in range(self.dim[1]):
69 | self._xy[i, :, 0] = self.x
70 | for i in range(self.dim[0]):
71 | self._xy[:, i, 1] = self.y
72 | self._xy.resize((self.dim[0] * self.dim[1], 2))
73 | return self._xy
74 |
75 |
76 | class Grid3D:
77 | '''
78 | Classes used to represent a three-dimensional grid.
79 | '''
80 |
81 | def __init__(self):
82 | self.x = None
83 | self.y = None
84 | self.z = None
85 | self.xran = None
86 | self.yran = None
87 | self.zran = None
88 | self._xyz = None
89 | self.dim = [-1, -1, -1] # width(x), height(y), long(z)
90 |
91 | def rectlinear(self, dim, xran, yran, zran):
92 | '''
93 | Initialize the three-dimensional grid according to the dimension, x range, y range, xrange.
94 |
95 | :param dim: array_like, array containing two integer. [width, height].
96 | :param xran: array_like, [xbegin, xend]. So the step of x is equal to (xend-xbegin)/(width-1).
97 | :param yran: array_like, [ybegin, yend].
98 | :param zran: array_like, [zbegin, zend].
99 | :return: None
100 | '''
101 | self.dim = dim
102 | self.xran = xran
103 | self.yran = yran
104 | self.zran = zran
105 | xstep = (xran[1] - xran[0]) / (dim[0] - 1)
106 | self.x = np.array([(i * xstep + xran[0]) for i in range(dim[0])])
107 | ystep = (yran[1] - yran[0]) / (dim[1] - 1)
108 | self.y = np.array([(i * ystep + yran[0]) for i in range(dim[1])])
109 | zstep = (zran[1] - zran[0]) / (dim[2] - 1)
110 | self.z = np.array([(i * zstep + zran[0]) for i in range(dim[2])])
111 | self._xyz = None
112 |
113 | def setXCoords(self, xcoords):
114 | '''
115 | Sets the x coordinate of the grid.
116 |
117 | :param xcoords: array_like, array containing all the coordinates along the x axis.
118 | :return: None
119 | '''
120 | self.x = np.array(xcoords)
121 | self.dim[0] = len(self.x)
122 | self.xran = [self.x.min(), self.x.max()]
123 | self._xyz = None
124 |
125 | def setYCoords(self, ycoords):
126 | '''
127 | Sets the y coordinate of the grid.
128 |
129 | :param ycoords: array_like, array containing all the coordinates along the y axis.
130 | :return: None
131 | '''
132 | self.y = np.array(ycoords)
133 | self.dim[1] = len(self.y)
134 | self.yran = [self.y.min(), self.y.max()]
135 | self._xyz = None
136 |
137 | def setZCoords(self, zcoords):
138 | '''
139 | Sets the z coordinate of the grid.
140 |
141 | :param zcoords: array_like, array containing all the coordinates along the z axis.
142 | :return: None
143 | '''
144 | self.z = np.array(zcoords)
145 | self.dim[2] = len(self.z)
146 | self.zran = [self.z.min(), self.z.max()]
147 | self._xyz = None
148 |
149 | def points(self):
150 | '''
151 | Returns an ndarray containing all coordinates on the grid,
152 | and the shape of the array is (width*height*long, 3).
153 |
154 | :return: ndarray
155 | '''
156 | if self._xyz is None:
157 | self._xyz = np.zeros((self.dim[2], self.dim[1], self.dim[0], 3))
158 | for i in range(self.dim[2]):
159 | for j in range(self.dim[1]):
160 | self._xyz[i, j, :, 0] = self.x
161 | for j in range(self.dim[0]):
162 | self._xyz[i, :, j, 1] = self.y
163 | self._xyz[i, :, :, 2] = self.z[i]
164 | self._xyz.resize((self.dim[0] * self.dim[1] * self.dim[2], 3))
165 | return self._xyz
166 |
--------------------------------------------------------------------------------
/src/tfinterpy/gslib/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # @Time : 2022/3/28 12:02
3 | # @Author : UCCU
4 |
--------------------------------------------------------------------------------
/src/tfinterpy/gslib/fileUtils.py:
--------------------------------------------------------------------------------
1 | import pandas as pd
2 |
3 |
4 | def readGslibPoints(filePath):
5 | '''
6 | Read points data from gslib file.
7 |
8 | :param filePath: str.
9 | :return: DataFrame object.
10 | '''
11 | columnNames = []
12 | with open(filePath, 'r') as fi:
13 | fi.readline()
14 | n = int(fi.readline().strip())
15 | for i in range(n):
16 | columnNames.append(fi.readline().strip())
17 | fi.close()
18 | df = pd.read_csv(filePath, sep=',|\s+', skiprows=n + 2, header=None, engine="python")
19 | df.columns = columnNames
20 | return df
21 |
22 |
23 | def saveGslibPoints(filePath, colNames, ndarray, comment="#"):
24 | '''
25 | Save points data to gslib file.
26 |
27 | :param filePath: str.
28 | :param colNames: list, column names.
29 | :param ndarray: ndarray, points and properties data.
30 | :param comment: str, comment on the first line of the gslib file.
31 | :return: None.
32 | '''
33 | fo = open(filePath, 'w')
34 | fo.write(comment + '\n')
35 | fo.write('{}\n'.format(len(colNames)))
36 | for name in colNames:
37 | fo.write(name + '\n')
38 | df = pd.DataFrame(ndarray)
39 | df.to_csv(fo, sep=' ', line_terminator='\n', index=False, header=False)
40 | fo.close()
41 |
42 |
43 | def saveGslibGrid(filePath, dim, begin, step, colNames, ndarray, comment=None):
44 | '''
45 | Save rectilinear grid data to gslib file.
46 |
47 | :param filePath: str.
48 | :param dim: list, [xnum, ynum, znum], xnum indicates the number of x coordinates.
49 | :param begin: list, [x,y,z], begin coordinates.
50 | :param step: list, [xstep,ystep,zstep], xstep indicates the step on x axis.
51 | :param colNames: list, column names.
52 | :param ndarray: ndarray, points and properties data.
53 | :param comment: str, comment on the first line of the gslib file.
54 | :return: None.
55 | '''
56 | fo = open(filePath, 'w')
57 | if comment is not None:
58 | fo.write('#' + comment + '\n')
59 | line = ' '.join(list(map(lambda x: str(x), dim)))
60 | fo.write(line + '\n')
61 | line = ' '.join(list(map(lambda x: str(x), begin)))
62 | fo.write(line + '\n')
63 | line = ' '.join(list(map(lambda x: str(x), step)))
64 | fo.write(line + '\n')
65 | df = pd.DataFrame(ndarray)
66 | df.columns = colNames
67 | df.to_csv(fo, sep=' ', line_terminator='\n', index=False)
68 | fo.close()
69 |
--------------------------------------------------------------------------------
/src/tfinterpy/gui/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # @Time : 2022/3/25 12:24
3 | # @Author : UCCU
4 |
--------------------------------------------------------------------------------
/src/tfinterpy/gui/canvas.py:
--------------------------------------------------------------------------------
1 | import matplotlib
2 | matplotlib.use("Qt5Agg")
3 | from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
4 | from matplotlib.figure import Figure
5 | import matplotlib.pyplot as plt
6 |
7 | #Set the global font size of matplotlib.
8 | plt.rcParams.update({"font.size":16})
9 |
10 | class Canvas(FigureCanvas):
11 | '''
12 | Matploblib canvas for embedding Qt widget.
13 | '''
14 |
15 | def __init__(self, width=5, height=4, dpi=100, parent=None):
16 | self.fig = Figure(figsize=(width, height), dpi=dpi)
17 | super(Canvas, self).__init__(self.fig)
18 | self.setParent(parent)
--------------------------------------------------------------------------------
/src/tfinterpy/idw.py:
--------------------------------------------------------------------------------
1 | from tfinterpy.utils import kSplit
2 | import numpy as np
3 | from scipy.spatial import cKDTree
4 |
5 |
6 | class IDW:
7 | '''
8 | Inverse Distance Weighted interpolator.
9 | '''
10 |
11 | def __init__(self, samples, mode='2d'):
12 | '''
13 | Initialize the interpolator using sample points.
14 |
15 | :param samples: ndarray, array containing all sample points. The last column must be the properties.
16 | For the case of two-dimensional interpolation, where each item is represented by [x,y,property].
17 | For the case of three-dimensional interpolation, where each item is represented by [x,y,z,property].
18 | :param mode: str, '2d' or '3d'.
19 | '''
20 | self.samples = samples
21 | self.mode = mode
22 | self._i = 2
23 | if mode == '3d' or mode == '3D':
24 | self._i = 3
25 |
26 | def execute(self, points, N=8, alpha=2):
27 | '''
28 | Perform interpolation for points and return result values.
29 |
30 | :param points: ndarray, array containing all the coordinate points to be interpolated.
31 | :param N: integer, neighborhood size.
32 | :param alpha: number, distance power factor.
33 | :return: ndarray, one-dimensional array containing interpolation result.
34 | '''
35 | tree = cKDTree(self.samples[:, :self._i])
36 | nbd, nbIdx = tree.query(points, k=N, eps=0.0)
37 | properties = np.zeros((len(points)))
38 | for idx, indice in enumerate(nbIdx):
39 | hs = nbd[idx]
40 | hs = hs ** alpha
41 | inv = 1 / (hs + 1e-8)
42 | total = np.sum(inv)
43 | weights = inv / total
44 | pro = np.dot(self.samples[:, self._i][indice], weights)
45 | properties[idx] = pro
46 | return properties
47 |
48 | def crossValidateKFold(self, K=10, N=8, alpha=2):
49 | '''
50 | Perform k-fold cross validation on sample points.
51 |
52 | :param K: integer.
53 | :param N: integer, neighborhood size.
54 | :param alpha: number, distance power factor.
55 | :return: tuple, tuple containing three list.
56 | The first list contains the absolute mean error for each fold,
57 | the second list contains the absolute standard deviation error for each fold,
58 | the last list contains the origin error for each fold.
59 | '''
60 | splits = kSplit(self.samples, K)
61 | absErrorMeans = []
62 | absErrorStds = []
63 | originalErrorList = []
64 | for i in range(K):
65 | concatenateList = []
66 | for j in range(K):
67 | if j == i:
68 | continue
69 | concatenateList.append(splits[j])
70 | p1 = np.concatenate(concatenateList)
71 | p2 = splits[i]
72 | if len(p2) == 0:
73 | break
74 | exe = IDW(p1, self.mode)
75 | es = exe.execute(p2[:, :self._i], N, alpha)
76 | error = p2[:, self._i] - es
77 | absError = np.abs(error)
78 | mean = absError.mean()
79 | std = absError.std()
80 | originalErrorList.append(error)
81 | absErrorMeans.append(mean)
82 | absErrorStds.append(std)
83 | return absErrorMeans, absErrorStds, originalErrorList
84 |
85 | def crossValidate(self, N=8, alpha=2):
86 | '''
87 | Perform leave-one-out cross validation on sample points.
88 |
89 | :param N: integer, neighborhood size.
90 | :param alpha: number, distance power factor.
91 | :return: tuple, tuple containing absolute mean error, absolute standard deviation error and origin error(ndarray).
92 | '''
93 | tree = cKDTree(self.samples[:, :self._i])
94 | nbd, nb_idx = tree.query(self.samples[:, :self._i], k=N + 1, eps=0.0)
95 | properties = np.zeros((len(self.samples)))
96 | for idx, indice in enumerate(nb_idx):
97 | indice = indice[1:]
98 | hs = nbd[idx][1:]
99 | hs = hs ** alpha
100 | inv = 1 / (hs + 1e-8)
101 | total = np.sum(inv)
102 | weights = inv / total
103 | pro = np.dot(self.samples[:, self._i][indice], weights)
104 | properties[idx] = pro
105 | error = properties - self.samples[:, self._i]
106 | absError = np.abs(error)
107 | mean = absError.mean()
108 | std = absError.std()
109 | return mean, std, error
110 |
--------------------------------------------------------------------------------
/src/tfinterpy/krige.py:
--------------------------------------------------------------------------------
1 | from scipy.spatial import cKDTree
2 | import numpy as np
3 | from tfinterpy.utils import kSplit, calcVecs
4 | from tfinterpy.variogram import NestVariogram
5 |
6 |
7 | class SK:
8 | '''
9 | Simple Kriging interpolator.
10 | '''
11 |
12 | def __init__(self, samples, mode="2d"):
13 | '''
14 | Initialize the interpolator using sample points.
15 |
16 | :param samples: ndarray, array containing all sample points. The last column must be the properties.
17 | For the case of two-dimensional interpolation, where each item is represented by [x,y,property].
18 | For the case of three-dimensional interpolation, where each item is represented by [x,y,z,property].
19 | :param mode: str, '2d' or '3d'.
20 | '''
21 | self.samples = samples
22 | self.mode = mode
23 | self._i = 2
24 | if mode.lower() == '3d':
25 | self._i = 3
26 | self.innerVecs = None
27 |
28 | def execute(self, points, N=8, variogram=None):
29 | '''
30 | Perform interpolation for points and return result values.
31 |
32 | :param points: ndarray, array containing all the coordinate points to be interpolated.
33 | :param N: integer, neighborhood size.
34 | :param variogram: variogram function or nest variogram object, default None.
35 | A linear variogram (lambda x:x) is used when the variogram is None.
36 | :return: tuple, tuple containing tow ndarray.
37 | The first ndarray representing the interpolation result,
38 | the second ndarray representing the kriging variance.
39 | '''
40 | if self.innerVecs is None:
41 | self.__calcInnerVecs__()
42 | if variogram is None:
43 | self.innerVars = np.linalg.norm(self.innerVecs, axis=2)
44 | variogram = lambda x: x
45 | elif variogram.__class__ == NestVariogram:
46 | self.innerVars = variogram(self.innerVecs)
47 | else:
48 | self.innerVars = np.linalg.norm(self.innerVecs, axis=2)
49 | self.innerVars = variogram(self.innerVars)
50 | if self.innerVars.shape[-1] == 1:
51 | self.innerVars = self.innerVars.reshape(self.innerVars.shape[:-1])
52 |
53 | tree = cKDTree(self.samples[:, :self._i])
54 | nbd, nbIdx = tree.query(points, k=N, eps=0.0)
55 | properties = np.zeros((len(points)))
56 | sigmas = np.zeros((len(points)))
57 | for idx, indice in enumerate(nbIdx):
58 | kmat = self.innerVars[indice][:, indice]
59 | if variogram.__class__ == NestVariogram:
60 | mvec = self.samples[indice, :self._i] - points[idx]
61 | mvec = variogram(mvec)
62 | else:
63 | mvec = variogram(nbd[idx])
64 | np.fill_diagonal(kmat, 0.0)
65 | try:
66 | lambvec = np.linalg.inv(kmat).dot(mvec)
67 | except:
68 | lambvec = np.linalg.pinv(kmat).dot(mvec)
69 | pro = np.dot(self.samples[:, self._i][indice], lambvec)
70 | properties[idx] = pro + np.mean(self.samples[:, self._i][indice]) * (1 - np.sum(lambvec))
71 | sigmas[idx] = np.dot(lambvec, mvec)
72 | return properties, sigmas
73 |
74 | def crossValidateKFold(self, K=10, N=8, variogram=None):
75 | '''
76 | Perform k-fold cross validation on sample points.
77 |
78 | :param K: integer.
79 | :param N: integer, neighborhood size.
80 | :param variogram: variogram function or nest variogram object, default None.
81 | A linear variogram (lambda x:x) is used when the variogram is None.
82 | :return: tuple, tuple containing three list.
83 | The first list contains the absolute mean error for each fold,
84 | the second list contains the absolute standard deviation error for each fold,
85 | the last list contains the origin error for each fold.
86 | '''
87 | splits = kSplit(self.samples, K)
88 | absErrorMeans = []
89 | absErrorStds = []
90 | originalErrorList = []
91 | for i in range(K):
92 | concatenateList = []
93 | for j in range(K):
94 | if j == i:
95 | continue
96 | concatenateList.append(splits[j])
97 | p1 = np.concatenate(concatenateList)
98 | p2 = splits[i]
99 | if len(p2) == 0:
100 | break
101 | exe = SK(p1, self.mode)
102 | es, _ = exe.execute(p2[:, :self._i], N, variogram)
103 | error = p2[:, self._i] - es
104 | absError = np.abs(error)
105 | mean = absError.mean()
106 | std = absError.std()
107 | originalErrorList.append(error)
108 | absErrorMeans.append(mean)
109 | absErrorStds.append(std)
110 | return absErrorMeans, absErrorStds, originalErrorList
111 |
112 | def crossValidate(self, N=8, variogram=None):
113 | '''
114 | Perform leave-one-out cross validation on sample points.
115 |
116 | :param N: integer, neighborhood size.
117 | :param variogram: variogram function or nest variogram object, default None.
118 | A linear variogram (lambda x:x) is used when the variogram is None.
119 | :return: tuple, tuple containing absolute mean error, absolute standard deviation error and origin error(ndarray).
120 | '''
121 | if self.innerVecs is None:
122 | self.__calcInnerVecs__()
123 | if variogram is None:
124 | self.innerVars = np.linalg.norm(self.innerVecs, axis=2)
125 | variogram = lambda x: x
126 | elif variogram.__class__ == NestVariogram:
127 | self.innerVars = variogram(self.innerVecs)
128 | else:
129 | self.innerVars = np.linalg.norm(self.innerVecs, axis=2)
130 | self.innerVars = variogram(self.innerVars)
131 | if self.innerVars.shape[-1] == 1:
132 | self.innerVars = self.innerVars.reshape(self.innerVars.shape[:-1])
133 |
134 | tree = cKDTree(self.samples[:, :self._i])
135 | nbd, nbIdx = tree.query(self.samples[:, :self._i], k=N + 1, eps=0.0)
136 | properties = np.zeros((len(self.samples)))
137 | for idx, indice in enumerate(nbIdx):
138 | indice = indice[1:]
139 | kmat = self.innerVars[indice][:, indice]
140 | if variogram.__class__ == NestVariogram:
141 | mvec = self.samples[indice, :self._i] - self.samples[idx, :self._i]
142 | mvec = variogram(mvec)
143 | else:
144 | mvec = variogram(nbd[idx][1:])
145 | np.fill_diagonal(kmat, 0.0)
146 | try:
147 | lambvec = np.linalg.inv(kmat).dot(mvec)
148 | except:
149 | lambvec = np.linalg.pinv(kmat).dot(mvec)
150 | pro = np.dot(self.samples[:, self._i][indice], lambvec)
151 | properties[idx] = pro + np.mean(self.samples[:, self._i][indice]) * (1 - np.sum(lambvec))
152 | error = properties - self.samples[:, self._i]
153 | absError = np.abs(error)
154 | mean = absError.mean()
155 | std = absError.std()
156 | return mean, std, error
157 |
158 | def __calcInnerVecs__(self):
159 | '''
160 | Compute vectors between sample points.
161 |
162 | :return: None.
163 | '''
164 | innerVecs = calcVecs(self.samples[:, :self._i], includeSelf=True)
165 | self.innerVecs = innerVecs.reshape((self.samples.shape[0], self.samples.shape[0], self._i))
166 |
167 |
168 | class OK:
169 | '''
170 | Ordinary Kriging interpolator.
171 | '''
172 |
173 | def __init__(self, samples, mode="2d"):
174 | '''
175 | Initialize the interpolator using sample points.
176 |
177 | :param samples: ndarray, array containing all sample points. The last column must be the properties.
178 | For the case of two-dimensional interpolation, where each item is represented by [x,y,property].
179 | For the case of three-dimensional interpolation, where each item is represented by [x,y,z,property].
180 | :param mode: str, '2d' or '3d'.
181 | '''
182 | self.samples = samples
183 | self.mode = mode
184 | self._i = 2
185 | if mode.lower() == '3d':
186 | self._i = 3
187 | self.innerVecs = None
188 |
189 | def execute(self, points, N=8, variogram=None):
190 | '''
191 | Perform interpolation for points and return result values.
192 |
193 | :param points: ndarray, array containing all the coordinate points to be interpolated.
194 | :param N: integer, neighborhood size.
195 | :param variogram: variogram function or nest variogram object, default None.
196 | A linear variogram (lambda x:x) is used when the variogram is None.
197 | :return: tuple, tuple containing tow ndarray.
198 | The first ndarray representing the interpolation result,
199 | the second ndarray representing the kriging variance.
200 | '''
201 | if self.innerVecs is None:
202 | self.__calcInnerVecs__()
203 | if variogram is None:
204 | self.innerVars = np.linalg.norm(self.innerVecs, axis=2)
205 | variogram = lambda x: x
206 | elif variogram.__class__ == NestVariogram:
207 | self.innerVars = variogram(self.innerVecs)
208 | else:
209 | self.innerVars = np.linalg.norm(self.innerVecs, axis=2)
210 | self.innerVars = variogram(self.innerVars)
211 | if self.innerVars.shape[-1] == 1:
212 | self.innerVars = self.innerVars.reshape(self.innerVars.shape[:-1])
213 |
214 | tree = cKDTree(self.samples[:, :self._i])
215 | nbd, nbIdx = tree.query(points, k=N, eps=0.0)
216 | properties = np.zeros((len(points)))
217 | sigmas = np.zeros((len(points)))
218 | kmat = np.ones((N + 1, N + 1))
219 | kmat[N, N] = 0.0
220 | mvec = np.ones((N + 1,))
221 | for idx, indice in enumerate(nbIdx):
222 | kmat[:N, :N] = self.innerVars[indice][:, indice]
223 | if variogram.__class__ == NestVariogram:
224 | vecs = self.samples[indice, :self._i] - points[idx]
225 | mvec[:N] = variogram(vecs)
226 | else:
227 | mvec[:N] = variogram(nbd[idx])
228 | np.fill_diagonal(kmat, 0.0)
229 | try:
230 | lambvec = np.linalg.inv(kmat).dot(mvec)
231 | except:
232 | lambvec = np.linalg.pinv(kmat).dot(mvec)
233 | properties[idx] = np.dot(self.samples[indice, self._i], lambvec[:N])
234 | sigmas[idx] = np.dot(lambvec, mvec)
235 | return properties, sigmas
236 |
237 | def crossValidateKFold(self, K=10, N=8, variogram=None):
238 | '''
239 | Perform k-fold cross validation on sample points.
240 |
241 | :param K: integer.
242 | :param N: integer, neighborhood size.
243 | :param variogram: variogram function or nest variogram object, default None.
244 | A linear variogram (lambda x:x) is used when the variogram is None.
245 | :return: tuple, tuple containing three list.
246 | The first list contains the absolute mean error for each fold,
247 | the second list contains the absolute standard deviation error for each fold,
248 | the last list contains the origin error for each fold.
249 | '''
250 | splits = kSplit(self.samples, K)
251 | absErrorMeans = []
252 | absErrorStds = []
253 | originalErrorList = []
254 | for i in range(K):
255 | concatenateList = []
256 | for j in range(K):
257 | if j == i:
258 | continue
259 | concatenateList.append(splits[j])
260 | p1 = np.concatenate(concatenateList)
261 | p2 = splits[i]
262 | if len(p2) == 0:
263 | break
264 | exe = OK(p1, self.mode)
265 | es, _ = exe.execute(p2[:, :self._i], N, variogram)
266 | error = p2[:, self._i] - es
267 | absError = np.abs(error)
268 | mean = absError.mean()
269 | std = absError.std()
270 | originalErrorList.append(error)
271 | absErrorMeans.append(mean)
272 | absErrorStds.append(std)
273 | return absErrorMeans, absErrorStds, originalErrorList
274 |
275 | def crossValidate(self, N=8, variogram=None):
276 | '''
277 | Perform leave-one-out cross validation on sample points.
278 |
279 | :param N: integer, neighborhood size.
280 | :param variogram: variogram function or nest variogram object, default None.
281 | A linear variogram (lambda x:x) is used when the variogram is None.
282 | :return: tuple, tuple containing absolute mean error, absolute standard deviation error and origin error(ndarray).
283 | '''
284 | if self.innerVecs is None:
285 | self.__calcInnerVecs__()
286 | if variogram is None:
287 | self.innerVars = np.linalg.norm(self.innerVecs, axis=2)
288 | variogram = lambda x: x
289 | elif variogram.__class__ == NestVariogram:
290 | self.innerVars = variogram(self.innerVecs)
291 | else:
292 | self.innerVars = np.linalg.norm(self.innerVecs, axis=2)
293 | self.innerVars = variogram(self.innerVars)
294 | if self.innerVars.shape[-1] == 1:
295 | self.innerVars = self.innerVars.reshape(self.innerVars.shape[:-1])
296 |
297 | tree = cKDTree(self.samples[:, :self._i])
298 | nbd, nbIdx = tree.query(self.samples[:, :self._i], k=N + 1, eps=0.0)
299 | properties = np.zeros((len(self.samples)))
300 | kmat = np.ones((N + 1, N + 1))
301 | kmat[N, N] = 0.0
302 | mvec = np.ones((N + 1,))
303 | for idx, indice in enumerate(nbIdx):
304 | indice = indice[1:]
305 | kmat[:N, :N] = self.innerVars[indice][:, indice]
306 | if variogram.__class__ == NestVariogram:
307 | vecs = self.samples[indice, :self._i] - self.samples[idx, :self._i]
308 | mvec[:N] = variogram(vecs)
309 | else:
310 | mvec[:N] = variogram(nbd[idx][1:])
311 | np.fill_diagonal(kmat, 0.0)
312 | try:
313 | lambvec = np.linalg.inv(kmat).dot(mvec)
314 | except:
315 | lambvec = np.linalg.pinv(kmat).dot(mvec)
316 | properties[idx] = np.dot(self.samples[:, self._i][indice], lambvec[:N])
317 | error = properties - self.samples[:, self._i]
318 | absError = np.abs(error)
319 | mean = absError.mean()
320 | std = absError.std()
321 | return mean, std, error
322 |
323 | def __calcInnerVecs__(self):
324 | '''
325 | Compute vectors between sample points.
326 |
327 | :return: None.
328 | '''
329 | innerVecs = calcVecs(self.samples[:, :self._i], includeSelf=True)
330 | self.innerVecs = innerVecs.reshape((self.samples.shape[0], self.samples.shape[0], self._i))
331 |
--------------------------------------------------------------------------------
/src/tfinterpy/tf/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/czwchenzhun/tfinterpy/9dc3b97260ec8b1d9d6631c33c3e19c298bb6f4a/src/tfinterpy/tf/__init__.py
--------------------------------------------------------------------------------
/src/tfinterpy/tf/commonLayer.py:
--------------------------------------------------------------------------------
1 | import tensorflow as tf
2 | import tensorflow.keras.backend as K
3 | from tensorflow.keras import layers
4 |
5 | class InvLayer(layers.Layer):
6 | def __init__(self):
7 | super(InvLayer, self).__init__()
8 |
9 | def call(self, mat):
10 | return tf.linalg.pinv(mat)
11 |
12 | class MeanLayer(layers.Layer):
13 | def __init__(self):
14 | super(MeanLayer, self).__init__()
15 |
16 | def call(self, vec):
17 | return K.mean(vec, axis=1)
18 |
19 | class SumLayer(layers.Layer):
20 | def __init__(self):
21 | super(SumLayer, self).__init__()
22 |
23 | def call(self, vec):
24 | return K.sum(vec, axis=1)
--------------------------------------------------------------------------------
/src/tfinterpy/tf/idw.py:
--------------------------------------------------------------------------------
1 | import tensorflow.keras.backend as K
2 | from tensorflow.keras import layers
3 | from tensorflow.keras.models import Model
4 | from scipy.spatial import cKDTree
5 | import numpy as np
6 | from tfinterpy.utils import kSplit
7 | from tfinterpy.tf.commonLayer import SumLayer
8 |
9 | def IDWModel(n=8, alpha=2):
10 | '''
11 | Construction a keras model for Inverse Distance Weighted algorithm.
12 |
13 | :param n: integer, neighborhood size.
14 | :param alpha: number, distance power factor.
15 | :return: keras' Model object.
16 | '''
17 | h_ = layers.Input(shape=(n,))
18 | pro = layers.Input(shape=(n,))
19 | h = h_ ** alpha
20 | hinv = 1 / (h + 1e-8)
21 | total = SumLayer()(hinv)
22 | total = layers.Reshape((1,))(total)
23 | weights = hinv / total
24 | estimate = layers.Dot(1)([pro, weights])
25 | model = Model(inputs=[h_, pro], outputs=estimate)
26 | return model
27 |
28 |
29 | class TFIDW:
30 | '''
31 | Tensorflow version of Inverse Distance Weighted interpolator.
32 | '''
33 |
34 | def __init__(self, samples, mode='2d'):
35 | '''
36 | Initialize the interpolator using sample points.
37 |
38 | :param samples: ndarray, array containing all sample points. The last column must be the properties.
39 | For the case of two-dimensional interpolation, where each item is represented by [x,y,property].
40 | For the case of three-dimensional interpolation, where each item is represented by [x,y,z,property].
41 | :param mode: str, '2d' or '3d'.
42 | '''
43 | self.samples = samples
44 | self.mode = mode
45 | self._i = 2
46 | if mode == '3d' or mode == '3D':
47 | self._i = 3
48 |
49 | def execute(self, points, N=8, alpha=2, batch_size=1000):
50 | '''
51 | Perform interpolation for points and return result values.
52 |
53 | :param points: ndarray, array containing all the coordinate points to be interpolated.
54 | :param N: integer, neighborhood size.
55 | :param alpha: number, distance power factor.
56 | :param batch_size: integer, size of each batch of data to be calculated.
57 | :return: ndarray, one-dimensional array containing interpolation result.
58 | '''
59 | self.model = IDWModel(N, alpha)
60 | tree = cKDTree(self.samples[:, :self._i])
61 | step = batch_size * 2
62 | num = int(np.ceil(len(points) / step))
63 | pros = np.empty((0, 1))
64 | for i in range(num):
65 | begin = i * step
66 | end = (i + 1) * step
67 | points_ = points[begin:end]
68 | nbd, nbIdx = tree.query(points_, k=N, eps=0.0)
69 | hList = []
70 | neighProList = []
71 | for idx, indice in enumerate(nbIdx):
72 | hList.append(nbd[idx])
73 | neighProList.append(self.samples[indice, self._i])
74 | hArr = np.array(hList)
75 | neighProArr = np.array(neighProList)
76 | pro = self.model.predict([hArr, neighProArr], batch_size=batch_size)
77 | pros = np.append(pros, pro)
78 | return pros
79 |
80 | def crossValidateKFold(self, K=10, N=8, alpha=2):
81 | '''
82 | Perform k-fold cross validation on sample points.
83 |
84 | :param K: integer.
85 | :param N: integer, neighborhood size.
86 | :param alpha: number, distance power factor.
87 | :return: tuple, tuple containing three list.
88 | The first list contains the absolute mean error for each fold,
89 | the second list contains the absolute standard deviation error for each fold,
90 | the last list contains the origin error for each fold.
91 | '''
92 | splits = kSplit(self.samples, K)
93 | absErrorMeans = []
94 | absErrorStds = []
95 | originalErrorList = []
96 | for i in range(K):
97 | concatenateList = []
98 | for j in range(K):
99 | if j == i:
100 | continue
101 | concatenateList.append(splits[j])
102 | p1 = np.concatenate(concatenateList)
103 | p2 = splits[i]
104 | if len(p2) == 0:
105 | break
106 | exe = TFIDW(p1, self.mode)
107 | es = exe.execute(p2[:, :self._i], N, alpha)
108 | error = p2[:, self._i] - es
109 | absError = np.abs(error)
110 | mean = absError.mean()
111 | std = absError.std()
112 | originalErrorList.extend(error.reshape(-1).tolist())
113 | absErrorMeans.append(mean)
114 | absErrorStds.append(std)
115 | return absErrorMeans, absErrorStds, originalErrorList
116 |
117 | def crossValidate(self, N=8, alpha=2):
118 | '''
119 | Perform leave-one-out cross validation on sample points.
120 |
121 | :param N: integer, neighborhood size.
122 | :param alpha: number, distance power factor.
123 | :return: tuple, tuple containing absolute mean error, absolute standard deviation error and origin error(ndarray).
124 | '''
125 | self.model = IDWModel(N, alpha)
126 | tree = cKDTree(self.samples[:, :self._i])
127 | nbd, nb_idx = tree.query(self.samples[:, :self._i], k=N + 1, eps=0.0)
128 | hList = []
129 | neighProList = []
130 | for idx, indice in enumerate(nb_idx):
131 | hList.append(nbd[idx][1:])
132 | neighProList.append(self.samples[indice[1:], self._i])
133 | hArr = np.array(hList)
134 | neighProArr = np.array(neighProList)
135 | pros = self.model.predict([hArr, neighProArr], batch_size=1000)
136 | pros = pros.reshape(-1)
137 | error = pros - self.samples[:, self._i]
138 | absError = np.abs(error)
139 | mean = absError.mean()
140 | std = absError.std()
141 | return mean, std, error
142 |
--------------------------------------------------------------------------------
/src/tfinterpy/tf/krige.py:
--------------------------------------------------------------------------------
1 | import tensorflow as tf
2 | import tensorflow.keras.backend as K
3 | from tensorflow.keras import layers
4 | from tensorflow.keras.models import Model
5 | from scipy.spatial import cKDTree
6 | import numpy as np
7 | from tfinterpy.utils import kSplit, calcVecs
8 | from tfinterpy.tf.variogramLayer import NestVariogramLayer
9 | from tfinterpy.tf.commonLayer import InvLayer, MeanLayer, SumLayer
10 |
11 | # tf.keras.backend.set_floatx('float64')
12 |
13 | def SKModel(n=8, variogramLayer=None, vecDim=2):
14 | '''
15 | Construction a keras model for Simple Kriging algorithm.
16 |
17 | :param n: integer, neighborhood size.
18 | :param variogramLayer: keras' layer, layer representing a variogram function.
19 | :param vecDim: integer, the dimension of the vector to be calculated.
20 | :return: keras' Model object.
21 | '''
22 | kmat = layers.Input(shape=(n, n))
23 | if variogramLayer != None and variogramLayer.__class__ == NestVariogramLayer:
24 | mvec_ = layers.Input(shape=(n, vecDim))
25 | else:
26 | mvec_ = layers.Input(shape=(n,))
27 | pro = layers.Input(shape=(n,))
28 | if variogramLayer != None:
29 | mvec = variogramLayer(mvec_)
30 | else:
31 | mvec = mvec_
32 | mvec = layers.Reshape((n, 1))(mvec)
33 | kmatInv = InvLayer()(kmat)
34 | lambvec = layers.Dot(1)([kmatInv, mvec])
35 | estimate = layers.Dot(1)([pro, lambvec])
36 | promean = MeanLayer()(pro)
37 | eps = SumLayer()(lambvec)
38 | promean = layers.Reshape((1,))(promean)
39 | eps = layers.Reshape((1,))(eps)
40 | estimate = estimate + promean * (1 - eps)
41 | lambvec = layers.Reshape((n,))(lambvec)
42 | mvec = layers.Reshape((n,))(mvec)
43 | sigma = layers.Dot(1)([lambvec, mvec])
44 | model = Model(inputs=[kmat, mvec_, pro], outputs=[estimate, sigma])
45 | return model
46 |
47 |
48 | class TFSK:
49 | '''
50 | Tensorflow version of Simple Kriging interpolator.
51 | '''
52 |
53 | def __init__(self, samples, mode='2d'):
54 | '''
55 | Initialize the interpolator using sample points.
56 |
57 | :param samples: ndarray, array containing all sample points. The last column must be the properties.
58 | For the case of two-dimensional interpolation, where each item is represented by [x,y,property].
59 | For the case of three-dimensional interpolation, where each item is represented by [x,y,z,property].
60 | :param mode: str, '2d' or '3d'.
61 | '''
62 | self.samples = samples
63 | self.mode = mode
64 | self._i = 2
65 | if mode.lower() == '3d':
66 | self._i = 3
67 | self.innerVecs = None
68 |
69 | def execute(self, points, N=8, variogramLayer=None, batch_size=10000):
70 | '''
71 | Perform interpolation for points and return result values.
72 |
73 | :param points: ndarray, array containing all the coordinate points to be interpolated.
74 | :param N: integer, neighborhood size.
75 | :param variogramLayer: keras' layer, layer representing a variogram function.
76 | :param batch_size: integer, size of each batch of data to be calculated.
77 | :return: tuple, tuple containing tow ndarray.
78 | The first ndarray representing the interpolation result,
79 | the second ndarray representing the kriging variance.
80 | '''
81 | self.N = N
82 | self.model = SKModel(N, variogramLayer, self._i)
83 | isNest = variogramLayer.__class__ == NestVariogramLayer
84 | if self.innerVecs is None:
85 | self.__calcInnerVecs__()
86 | if variogramLayer is None:
87 | self.innerVars = np.linalg.norm(self.innerVecs, axis=2)
88 | elif isNest:
89 | self.innerVars = variogramLayer(self.innerVecs).numpy()
90 | else:
91 | self.innerVars = np.linalg.norm(self.innerVecs, axis=2)
92 | self.innerVars = variogramLayer(self.innerVars).numpy()
93 | if self.innerVars.shape[-1] == 1:
94 | self.innerVars = self.innerVars.reshape(self.innerVars.shape[:-1])
95 |
96 | tree = cKDTree(self.samples[:, :self._i])
97 | step = batch_size * 3
98 | num = int(np.ceil(len(points) / step))
99 | pros = np.empty((0, 1))
100 | sigmas = np.empty((0, 1))
101 | init = False
102 | for i in range(num):
103 | begin = i * step
104 | end = (i + 1) * step
105 | if end > len(points):
106 | end = len(points)
107 | if not init or i == num - 1:
108 | kmatArr = np.zeros((end - begin, N, N))
109 | if isNest:
110 | mvecArr = np.zeros((end - begin, N, self._i))
111 | else:
112 | mvecArr = np.zeros((end - begin, N))
113 | neighProArr = np.zeros((end - begin, N))
114 | init = True
115 | points_ = points[begin:end]
116 | nbd, nbIdx = tree.query(points_, k=N, eps=0.0)
117 | for idx, indice in enumerate(nbIdx):
118 | kmatArr[idx] = self.innerVars[indice][:, indice]
119 | if isNest:
120 | mvecArr[idx] = self.samples[indice, :self._i] - points_[idx]
121 | else:
122 | mvecArr[idx] = nbd[idx]
123 | neighProArr[idx] = self.samples[indice, self._i]
124 | pro, sigma = self.model.predict([kmatArr, mvecArr, neighProArr], batch_size=batch_size)
125 | pros = np.append(pros, pro)
126 | sigmas = np.append(sigmas, sigma)
127 | return pros, sigmas
128 |
129 | def crossValidateKFold(self, K=10, N=8, variogramLayer=None):
130 | '''
131 | Perform k-fold cross validation on sample points.
132 |
133 | :param K: integer.
134 | :param N: integer, neighborhood size.
135 | :param variogramLayer: keras' layer, layer representing a variogram function.
136 | :return: tuple, tuple containing three list.
137 | The first list contains the absolute mean error for each fold,
138 | the second list contains the absolute standard deviation error for each fold,
139 | the last list contains the origin error for each fold.
140 | '''
141 | splits = kSplit(self.samples, K)
142 | absErrorMeans = []
143 | absErrorStds = []
144 | originalErrorList = []
145 | for i in range(K):
146 | concatenateList = []
147 | for j in range(K):
148 | if j == i:
149 | continue
150 | concatenateList.append(splits[j])
151 | p1 = np.concatenate(concatenateList)
152 | p2 = splits[i]
153 | if len(p2) == 0:
154 | break
155 | exe = TFSK(p1, self.mode)
156 | es, _ = exe.execute(p2[:, :self._i], N, variogramLayer)
157 | error = p2[:, self._i] - es
158 | absError = np.abs(error)
159 | mean = absError.mean()
160 | std = absError.std()
161 | originalErrorList.extend(error.reshape(-1).tolist())
162 | absErrorMeans.append(mean)
163 | absErrorStds.append(std)
164 | return absErrorMeans, absErrorStds, originalErrorList
165 |
166 | def crossValidate(self, N=8, variogramLayer=None):
167 | '''
168 | Perform leave-one-out cross validation on sample points.
169 |
170 | :param N: integer, neighborhood size.
171 | :param variogramLayer: keras' layer, layer representing a variogram function.
172 | :return: tuple, tuple containing absolute mean error, absolute standard deviation error and origin error(ndarray).
173 | '''
174 | self.N = N
175 | self.model = SKModel(N, variogramLayer, self._i)
176 | isNest = variogramLayer.__class__ == NestVariogramLayer
177 | if self.innerVecs is None:
178 | self.__calcInnerVecs__()
179 | if variogramLayer is None:
180 | self.innerVars = np.linalg.norm(self.innerVecs, axis=2)
181 | elif isNest:
182 | self.innerVars = variogramLayer(self.innerVecs).numpy()
183 | else:
184 | self.innerVars = np.linalg.norm(self.innerVecs, axis=2)
185 | self.innerVars = variogramLayer(self.innerVars).numpy()
186 | if self.innerVars.shape[-1] == 1:
187 | self.innerVars = self.innerVars.reshape(self.innerVars.shape[:-1])
188 |
189 | tree = cKDTree(self.samples[:, :self._i])
190 | nbd, nbIdx = tree.query(self.samples[:, :self._i], k=N + 1, eps=0.0)
191 | L = len(self.samples)
192 | kmatArr = np.zeros((L, N, N))
193 | if isNest:
194 | mvecArr = np.zeros((L, N, self._i))
195 | else:
196 | mvecArr = np.zeros((L, N))
197 | neighProArr = np.zeros((L, N))
198 | for idx, indice in enumerate(nbIdx):
199 | indice = indice[1:]
200 | kmatArr[idx] = self.innerVars[indice][:, indice]
201 | if isNest:
202 | mvecArr[idx] = self.samples[indice, :self._i] - self.samples[idx, :self._i]
203 | else:
204 | mvecArr[idx] = nbd[idx][1:]
205 | neighProArr[idx] = self.samples[indice, self._i]
206 | pros, _ = self.model.predict([kmatArr, mvecArr, neighProArr], batch_size=10000)
207 | pros = pros.reshape(-1)
208 | error = pros - self.samples[:, self._i]
209 | absError = np.abs(error)
210 | mean = absError.mean()
211 | std = absError.std()
212 | return mean, std, error
213 |
214 | def __calcInnerVecs__(self):
215 | '''
216 | Compute vectors between sample points.
217 |
218 | :return: None.
219 | '''
220 | innerVecs = calcVecs(self.samples[:, :self._i], includeSelf=True)
221 | self.innerVecs = innerVecs.reshape((self.samples.shape[0], self.samples.shape[0], self._i))
222 |
223 |
224 | def OKModel(n=8, variogramLayer=None, vecDim=2):
225 | '''
226 | Construction a keras model for Ordinary Kriging algorithm.
227 |
228 | :param n: integer, neighborhood size.
229 | :param variogramLayer: keras' layer, layer representing a variogram function.
230 | :param vecDim: integer, the dimension of the vector to be calculated.
231 | :return: keras' Model object.
232 | '''
233 | mat1 = np.ones((n + 1, n + 1))
234 | mat1[n] = 0
235 | mat1[:, n] = 0
236 | mat1 = tf.constant(mat1)
237 | mat2 = np.zeros((n + 1, n + 1))
238 | mat2[n] = 1
239 | mat2[:, n] = 1
240 | mat2[n, n] = 0
241 | mat2 = tf.constant(mat2)
242 |
243 | mat3 = np.ones((n + 1, 1))
244 | mat3[n] = 0
245 | mat3 = tf.constant(mat3)
246 | mat4 = np.zeros((n + 1, 1))
247 | mat4[n] = 1
248 | mat4 = tf.constant(mat4)
249 |
250 | kmat_ = layers.Input(shape=(n + 1, n + 1))
251 | if variogramLayer != None and variogramLayer.__class__ == NestVariogramLayer:
252 | mvec_ = layers.Input(shape=(n + 1, vecDim))
253 | else:
254 | mvec_ = layers.Input(shape=(n + 1,))
255 | pro = layers.Input(shape=(n,))
256 | if variogramLayer != None:
257 | mvec = variogramLayer(mvec_)
258 | mvec = layers.Reshape((n + 1, 1))(mvec)
259 |
260 | kmat = kmat_
261 | kmat = kmat * mat1
262 | kmat = kmat + mat2
263 | mvec = mvec * mat3
264 | mvec = mvec + mat4
265 | else:
266 | kmat = kmat_
267 | mvec = mvec_
268 | mvec = layers.Reshape((n + 1, 1))(mvec)
269 | kmatInv = InvLayer()(kmat)
270 | lambvec = layers.Dot(1)([kmatInv, mvec])
271 | estimate = layers.Dot(1)([pro, lambvec[:, :n]])
272 |
273 | lambvec = layers.Reshape((n + 1,))(lambvec)
274 | mvec = layers.Reshape((n + 1,))(mvec)
275 | sigma = layers.Dot(1)([lambvec, mvec])
276 | model = Model(inputs=[kmat_, mvec_, pro], outputs=[estimate, sigma])
277 | return model
278 |
279 |
280 | class TFOK:
281 | '''
282 | Tensorflow version of Ordinary Kriging interpolator.
283 | '''
284 |
285 | def __init__(self, samples, mode='2d'):
286 | '''
287 | Initialize the interpolator using sample points.
288 |
289 | :param samples: ndarray, array containing all sample points. The last column must be the properties.
290 | For the case of two-dimensional interpolation, where each item is represented by [x,y,property].
291 | For the case of three-dimensional interpolation, where each item is represented by [x,y,z,property].
292 | :param mode: str, '2d' or '3d'.
293 | '''
294 | self.samples = samples
295 | self.mode = mode
296 | self._i = 2
297 | if mode.lower() == '3d':
298 | self._i = 3
299 | self.innerVecs = None
300 |
301 | def execute(self, points, N=8, variogramLayer=None, batch_size=10000):
302 | '''
303 | Perform interpolation for points and return result values.
304 |
305 | :param points: ndarray, array containing all the coordinate points to be interpolated.
306 | :param N: integer, neighborhood size.
307 | :param variogramLayer: keras' layer, layer representing a variogram function.
308 | :param batch_size: integer, size of each batch of data to be calculated.
309 | :return: tuple, tuple containing tow ndarray.
310 | The first ndarray representing the interpolation result,
311 | the second ndarray representing the kriging variance.
312 | '''
313 | self.N = N
314 | self.model = OKModel(N, variogramLayer, self._i)
315 | isNest = variogramLayer.__class__ == NestVariogramLayer
316 | if self.innerVecs is None:
317 | self.__calcInnerVecs__()
318 | if variogramLayer is None:
319 | self.innerVars = np.linalg.norm(self.innerVecs, axis=2)
320 | elif isNest:
321 | self.innerVars = variogramLayer(self.innerVecs).numpy()
322 | else:
323 | self.innerVars = np.linalg.norm(self.innerVecs, axis=2)
324 | self.innerVars = variogramLayer(self.innerVars).numpy()
325 | if self.innerVars.shape[-1] == 1:
326 | self.innerVars = self.innerVars.reshape(self.innerVars.shape[:-1])
327 |
328 | tree = cKDTree(self.samples[:, :self._i])
329 | step = batch_size * 3
330 | num = int(np.ceil(len(points) / step))
331 | pros = np.empty((0, 1))
332 | sigmas = np.empty((0, 1))
333 | init = False
334 | for i in range(num):
335 | begin = i * step
336 | end = (i + 1) * step
337 | if end > len(points):
338 | end = len(points)
339 | if not init or i == num - 1:
340 | kmatArr = np.ones((end - begin, N + 1, N + 1))
341 | for j in range(end - begin):
342 | kmatArr[j, N, N] = 0.0
343 | if isNest:
344 | mvecArr = np.zeros((end - begin, N + 1, self._i))
345 | else:
346 | mvecArr = np.ones((end - begin, N + 1))
347 | neighProArr = np.zeros((end - begin, N))
348 | init = True
349 | points_ = points[begin:end]
350 | nbd, nbIdx = tree.query(points_, k=self.N, eps=0.0)
351 | for idx, indice in enumerate(nbIdx):
352 | kmatArr[idx, :N, :N] = self.innerVars[indice][:, indice]
353 | if isNest:
354 | mvecArr[idx, :N] = self.samples[indice, :self._i] - points_[idx]
355 | else:
356 | mvecArr[idx, :N] = nbd[idx]
357 | neighProArr[idx] = self.samples[indice, self._i]
358 | pro, sigma = self.model.predict([kmatArr, mvecArr, neighProArr], batch_size=batch_size)
359 | pros = np.append(pros, pro)
360 | sigmas = np.append(sigmas, sigma)
361 | return pros, sigmas
362 |
363 | def crossValidateKFold(self, K=10, N=8, variogramLayer=None):
364 | '''
365 | Perform k-fold cross validation on sample points.
366 |
367 | :param K: integer.
368 | :param N: integer, neighborhood size.
369 | :param variogramLayer: keras' layer, layer representing a variogram function.
370 | :return: tuple, tuple containing three list.
371 | The first list contains the absolute mean error for each fold,
372 | the second list contains the absolute standard deviation error for each fold,
373 | the last list contains the origin error for each fold.
374 | '''
375 | splits = kSplit(self.samples, K)
376 | absErrorMeans = []
377 | absErrorStds = []
378 | originalErrorList = []
379 | for i in range(K):
380 | concatenateList = []
381 | for j in range(K):
382 | if j == i:
383 | continue
384 | concatenateList.append(splits[j])
385 | p1 = np.concatenate(concatenateList)
386 | p2 = splits[i]
387 | if len(p2) == 0:
388 | break
389 | exe = TFOK(p1, self.mode)
390 | es, _ = exe.execute(p2[:, :self._i], N, variogramLayer)
391 | error = p2[:, self._i] - es
392 | absError = np.abs(error)
393 | mean = absError.mean()
394 | std = absError.std()
395 | originalErrorList.extend(error.reshape(-1).tolist())
396 | absErrorMeans.append(mean)
397 | absErrorStds.append(std)
398 | return absErrorMeans, absErrorStds, originalErrorList
399 |
400 | def crossValidate(self, N=8, variogramLayer=None):
401 | '''
402 | Perform leave-one-out cross validation on sample points.
403 |
404 | :param N: integer, neighborhood size.
405 | :param variogramLayer: keras' layer, layer representing a variogram function.
406 | :return: tuple, tuple containing absolute mean error, absolute standard deviation error and origin error(ndarray).
407 | '''
408 | self.N = N
409 | self.model = OKModel(N, variogramLayer, self._i)
410 | isNest = variogramLayer.__class__ == NestVariogramLayer
411 | if self.innerVecs is None:
412 | self.__calcInnerVecs__()
413 | if variogramLayer is None:
414 | self.innerVars = np.linalg.norm(self.innerVecs, axis=2)
415 | elif isNest:
416 | self.innerVars = variogramLayer(self.innerVecs).numpy()
417 | else:
418 | self.innerVars = np.linalg.norm(self.innerVecs, axis=2)
419 | self.innerVars = variogramLayer(self.innerVars).numpy()
420 | if self.innerVars.shape[-1] == 1:
421 | self.innerVars = self.innerVars.reshape(self.innerVars.shape[:-1])
422 |
423 | tree = cKDTree(self.samples[:, :self._i])
424 | nbd, nbIdx = tree.query(self.samples[:, :self._i], k=N + 1, eps=0.0)
425 | L = len(self.samples)
426 | kmatArr = np.ones((L, N + 1, N + 1))
427 | for j in range(L):
428 | kmatArr[j, N, N] = 0.0
429 | if isNest:
430 | mvecArr = np.zeros((L, N + 1, self._i))
431 | else:
432 | mvecArr = np.ones((L, N + 1))
433 | neighProArr = np.zeros((L, N))
434 | for idx, indice in enumerate(nbIdx):
435 | indice = indice[1:]
436 | kmatArr[idx, :N, :N] = self.innerVars[indice][:, indice]
437 | if isNest:
438 | mvecArr[idx, :N] = self.samples[indice, :self._i] - self.samples[idx, :self._i]
439 | else:
440 | mvecArr[idx, :N] = nbd[idx][1:]
441 | neighProArr[idx] = self.samples[indice, self._i]
442 | pros, _ = self.model.predict([kmatArr, mvecArr, neighProArr], batch_size=10000)
443 | pros = pros.reshape(-1)
444 | error = pros - self.samples[:, self._i]
445 | absError = np.abs(error)
446 | mean = absError.mean()
447 | std = absError.std()
448 | return mean, std, error
449 |
450 | def __calcInnerVecs__(self):
451 | '''
452 | Compute vectors between sample points.
453 |
454 | :return: None.
455 | '''
456 | innerVecs = calcVecs(self.samples[:, :self._i], includeSelf=True)
457 | self.innerVecs = innerVecs.reshape((self.samples.shape[0], self.samples.shape[0], self._i))
458 |
--------------------------------------------------------------------------------
/src/tfinterpy/tf/variogramLayer.py:
--------------------------------------------------------------------------------
1 | import tensorflow as tf
2 | from tensorflow.keras import layers
3 |
4 | tf.keras.backend.set_floatx('float64')
5 |
6 | class LinearLayer(layers.Layer):
7 | '''
8 | The keras layer representing the linear variogram function model.
9 | '''
10 |
11 | def __init__(self, slope, C0):
12 | super(LinearLayer, self).__init__()
13 | self.slope = tf.constant(slope)
14 | self.C0 = tf.constant(C0)
15 |
16 | def call(self, h):
17 | return h * self.slope + self.C0
18 |
19 |
20 | class PowerLayer(layers.Layer):
21 | '''
22 | The keras layer representing the power variogram function model.
23 | '''
24 |
25 | def __init__(self, scale, exp, C0):
26 | super(PowerLayer, self).__init__()
27 | self.scale = tf.constant(scale)
28 | self.exp = tf.constant(exp)
29 | self.C0 = tf.constant(C0)
30 |
31 | def call(self, h):
32 | return self.scale * (h ** self.exp) + self.C0
33 |
34 |
35 | class GaussianLayer(layers.Layer):
36 | '''
37 | The keras layer representing the gaussian variogram function model.
38 | '''
39 |
40 | def __init__(self, C, a, C0):
41 | super(GaussianLayer, self).__init__()
42 | self.C = tf.constant(C)
43 | self.a_2 = tf.constant((a * 4 / 7) ** 2)
44 | self.C0 = tf.constant(C0)
45 |
46 | def call(self, h):
47 | return self.C * (1.0 - tf.exp(-1.0 * (h ** 2.0) / self.a_2)) + self.C0
48 |
49 |
50 | class ExponentLayer(layers.Layer):
51 | '''
52 | The keras layer representing the exponent variogram function model.
53 | '''
54 |
55 | def __init__(self, C, a, C0):
56 | super(ExponentLayer, self).__init__()
57 | self.C = tf.constant(C)
58 | self.a_ = tf.constant(a / 3.0)
59 | self.C0 = tf.constant(C0)
60 |
61 | def call(self, h):
62 | return self.C * (1.0 - tf.exp(-1.0 * h / self.a_)) + self.C0
63 |
64 |
65 | class SphericalLayer(layers.Layer):
66 | '''
67 | The keras layer representing the spherical variogram function model.
68 | '''
69 |
70 | def __init__(self, C, a, C0):
71 | super(SphericalLayer, self).__init__()
72 | self.C = tf.constant(C)
73 | self.a = tf.constant(a)
74 | self.a2 = tf.constant(2 * a)
75 | self.a2_3 = tf.constant(2 * self.a ** 3)
76 | self.C0 = tf.constant(C0)
77 |
78 | def call(self, h):
79 | condition = tf.greater(h, self.a)
80 | return tf.where(condition, self.C + self.C0, self.C * (h * 3.0 / self.a2 - h ** 3.0 / self.a2_3) + self.C0)
81 |
82 |
83 | class NestVariogramLayer(layers.Layer):
84 | '''
85 | The keras layer representing the nested variogram functions.
86 | '''
87 |
88 | def __init__(self, variogramLayers, unitVectors):
89 | '''
90 | Construct a nested variogram function layer.
91 |
92 | :param variogramLayers: list, containing variogram layers.
93 | :param unitVectors: array_like, unit vectors corresponding to the direction.
94 | '''
95 | super(NestVariogramLayer, self).__init__()
96 | self.variogramLayers = variogramLayers
97 | self.unitVectors = unitVectors
98 | if len(self.unitVectors.shape) == 2:
99 | self.unitVectors = self.unitVectors.reshape((*self.unitVectors.shape, 1))
100 |
101 | def call(self, vec):
102 | total = 0
103 | for idx, variogramLayer in enumerate(self.variogramLayers):
104 | h = tf.abs(tf.matmul(vec, self.unitVectors[idx]))
105 | var = variogramLayer(h)
106 | total += var
107 | return total
108 |
109 |
110 | VariogramLayerMap = {
111 | "gaussian": GaussianLayer,
112 | "exponent": ExponentLayer,
113 | "spherical": SphericalLayer,
114 | "linear": LinearLayer,
115 | "power": PowerLayer,
116 | }
117 |
118 |
119 | def getVariogramLayer(variogramBuilder):
120 | '''
121 | Construct variogram layer by variogram builder.
122 |
123 | :param variogramBuilder: VariogramBuilder object.
124 | :return: keras' layer object.
125 | '''
126 | LayerClass = VariogramLayerMap[variogramBuilder.model]
127 | vl = LayerClass(*variogramBuilder.params)
128 | return vl
129 |
130 |
131 | def getNestVariogramLayer(variogramBuilders, unitVectors):
132 | '''
133 | Construct nested variogram layer by variogram builders and corresponding unit vectors.
134 |
135 | :param variogramBuilders: list, containing variogram builders.
136 | :param unitVectors: array_like, unit vectors corresponding to the direction.
137 | :return: keras' layer object.
138 | '''
139 | vls = []
140 | for vb in variogramBuilders:
141 | vl = getVariogramLayer(vb)
142 | vls.append(vl)
143 | return NestVariogramLayer(vls, unitVectors)
144 |
--------------------------------------------------------------------------------
/src/tfinterpy/utils.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 |
3 |
4 | def h2(p1, p2):
5 | '''
6 | Return the square of distance between p1 and p2.
7 | p1 and p2 can be either a one-dimensional array representing a single
8 | coordinate point or an ndarray containing multiple coordinate points.
9 | The shapes of p1 and p2 should be the same.
10 |
11 | :param p1: array_like.
12 | :param p2: array_like.
13 | :return: ndarray.
14 | '''
15 | diff = np.square(np.subtract(p1, p2))
16 | return np.sum(diff, axis=-1)
17 |
18 |
19 | def h(p1, p2):
20 | '''
21 | Return the distance between p1 and p2.
22 | p1 and p2 can be either a one-dimensional array representing a single
23 | coordinate point or an ndarray containing multiple coordinate points.
24 | The shapes of p1 and p2 should be the same.
25 |
26 | :param p1: array_like.
27 | :param p2: array_like.
28 | :return: ndarray.
29 | '''
30 | return np.sqrt(h2(p1, p2))
31 |
32 |
33 | def ha(p1, p2):
34 | '''
35 | Return the distance and angele between p1 and p2.
36 | p1 and p2 can be either a one-dimensional array representing a single
37 | coordinate point or an ndarray containing multiple coordinate points.
38 | The shapes of p1 and p2 should be the same.
39 |
40 | :param p1: array_like.
41 | :param p2: array_like.
42 | :return: tuple, tuple containing two ndarray.
43 | The first ndarray representing the distance,
44 | the second list representing the angle, the angle range is [0,PI].
45 | '''
46 | diff = np.subtract(p1, p2)
47 | h = np.sqrt(np.sum(np.square(diff), axis=-1))
48 | if diff.ndim == 1:
49 | angle = np.arctan2(diff[1], diff[0])
50 | angle = angle + np.pi if angle < 0 else angle
51 | else:
52 | angle = np.arctan2(diff[:, 1], diff[:, 0])
53 | angle[angle < 0] += np.pi
54 | return h, angle
55 |
56 |
57 | def calcHV(data, dim=2, attrib_col=2):
58 | '''
59 | Calculates the distance and variation between data.
60 |
61 | :param data: ndarray, array containing coordinates and attributes.
62 | :param dim: integer, indicates whether the coordinates are 2d or 3d.
63 | :param attrib_col: integer, indicates which column is property.
64 | :return: ndarray, the first column is distance, the second column is variation.
65 | '''
66 | if dim == 3 and attrib_col < 3:
67 | attrib_col = 3
68 | arr = np.empty((0, 2), dtype="float32")
69 | size = data.shape[0]
70 | for i in range(size - 1):
71 | dis = h(data[i + 1:, :dim], data[i, :dim])
72 | halfvar = 0.5 * ((data[i + 1:, attrib_col] - data[i, attrib_col]) ** 2)
73 | dis.resize((dis.shape[0], 1))
74 | halfvar.resize((halfvar.shape[0], 1))
75 | arr = np.append(arr, np.concatenate([dis, halfvar], axis=1), axis=0)
76 | return arr
77 |
78 |
79 | def calcHAV(data, attrib_col=2):
80 | '''
81 | Calculates the distance, angle and variation between data.
82 |
83 | :param data: ndarray, array containing coordinates and attributes.
84 | :param attrib_col: integer, indicates which column is property.
85 | :return: ndarray, the first column is distance,
86 | the second column is angle (range is [0, PI]),
87 | the third column is variation.
88 | '''
89 | dim = 2
90 | if attrib_col < 2:
91 | attrib_col = 2
92 | arr = np.empty((0, 3), dtype="float32")
93 | size = data.shape[0]
94 | for i in range(size - 1):
95 | dis, angle = ha(data[i + 1:, :dim], data[i, :dim])
96 | halfvar = 0.5 * ((data[i + 1:, attrib_col] - data[i, attrib_col]) ** 2)
97 | dis.resize((dis.shape[0], 1))
98 | angle.resize((angle.shape[0], 1))
99 | halfvar.resize((halfvar.shape[0], 1))
100 | arr = np.append(arr, np.concatenate([dis, angle, halfvar], axis=1), axis=0)
101 | return arr
102 |
103 |
104 | def calcHAVByVecs(vecs):
105 | '''
106 | Calculates the distance, angle and variation according to vectors.
107 |
108 | :param vecs: ndarray, vectors containing 2d coordinates' difference and properties' difference.
109 | :return: ndarray, the first column is distance,
110 | the second column is angle (range is [0, PI]),
111 | the third column is variation.
112 | '''
113 | distance = np.linalg.norm(vecs[:, :2], axis=1)
114 | angle = np.arctan2(vecs[:, 1], vecs[:, 0])
115 | angle[angle < 0] += np.pi
116 | var = 0.5 * (vecs[:, 2] ** 2)
117 | hav = np.zeros((len(vecs), 3))
118 | hav[:, 0] = distance
119 | hav[:, 1] = angle
120 | hav[:, 2] = var
121 | return hav
122 |
123 |
124 | def calcHABVByVecs(vecs):
125 | '''
126 | Calculates the distance, azimuth(alpha), dip(beta) and variation according to vectors.
127 |
128 | :param vecs: ndarray, vectors containing 3d coordinates' difference and properties' difference.
129 | :return: ndarray, the first column is distance,
130 | the second column is azimuth(alpha) (range is [0, PI]),
131 | the second column is dip(beta) (range is [0, PI]),
132 | the fourth column is variation.
133 | '''
134 | distance = np.linalg.norm(vecs[:, :3], axis=1)
135 | azimuth = np.arctan2(vecs[:, 1], vecs[:, 0])
136 | azimuth[azimuth < 0] += np.pi
137 | norm = np.linalg.norm(vecs[:, :2], axis=1)
138 | dip = np.arctan2(vecs[:, 2], norm)
139 | dip[dip < 0] += np.pi
140 | var = 0.5 * (vecs[:, 3] ** 2)
141 | habv = np.zeros((len(vecs), 4))
142 | habv[:, 0] = distance
143 | habv[:, 1] = azimuth
144 | habv[:, 2] = dip
145 | habv[:, 3] = var
146 | return habv
147 |
148 |
149 | def calcVecs(data, includeSelf=False, repeat=True):
150 | '''
151 | Compute vectors between data.
152 |
153 | :param data: ndarray, two-dimensional array.
154 | :param includeSelf: boolean, whether to subtract the vector from itself.
155 | :param repeat: boolean, whether to calculate the two points that have subtracted from each other.
156 | :return: ndarray, vectors.
157 | '''
158 | L = len(data)
159 | if repeat:
160 | vecs = []
161 | if includeSelf:
162 | for i in range(L):
163 | vec = data - data[i]
164 | vecs.append(vec)
165 | else:
166 | _indice = [i for i in range(L)]
167 | for i in range(L):
168 | indice = list(_indice)
169 | indice.pop(i)
170 | vec = data[indice] - data[i]
171 | vecs.append(vec)
172 | vecs = np.array(vecs)
173 | return vecs.reshape((vecs.shape[0] * vecs.shape[1], vecs.shape[2]))
174 | else:
175 | vecs = np.empty((0, data.shape[1]))
176 | for i in range(L - 1):
177 | vec = data[i + 1:] - data[i]
178 | vecs = np.append(vecs, vec, axis=0)
179 | return vecs
180 |
181 |
182 | def kSplit(ndarray, k):
183 | '''
184 | Split the ndarray into k fold.
185 |
186 | :param ndarray: ndarray.
187 | :param k: integer, fold number.
188 | :return: list, list containing all fold.
189 | '''
190 | size = ndarray.shape[0]
191 | step = size // k
192 | if size % k != 0:
193 | step += 1
194 | splits = []
195 | for i in range(k):
196 | begin = int(i * step)
197 | end = int((i + 1) * step)
198 | if i == k - 1:
199 | splits.append(ndarray[begin:])
200 | else:
201 | splits.append(ndarray[begin:end])
202 | return splits
203 |
--------------------------------------------------------------------------------
/src/tfinterpy/variogram.py:
--------------------------------------------------------------------------------
1 | from tfinterpy.utils import *
2 | from tfinterpy.variogramExp import search2d, search3d
3 | from tfinterpy.variogramModel import variogramModel, VariogramModelMap
4 | from scipy.optimize import least_squares
5 |
6 | EPS = 1e-16
7 |
8 | def resident(params, x, y, variogram_function):
9 | '''
10 | This function is used to calculate resident.
11 |
12 | :param params: tuple, represents the parameters passed to the variogram function.
13 | :param x: number or ndarray, distance.
14 | :param y: number or ndarray, semivariance.
15 | :param variogram_function: function, variogram function.
16 | :return: number or ndarray, resident=( variogram(x,params[0],...,params[n])-y )^2
17 | '''
18 | error = variogram_function(x, *params) - y
19 | return error ** 2
20 |
21 |
22 | def getX0AndBnds(h, y, variogram_model):
23 | '''
24 | Calculate the initial value and range of parameters(nugget, sill, range, ...)
25 | according to the variogram function model.
26 |
27 | :param h: array_like, distance.
28 | :param y: array_like, semivariance.
29 | :param variogram_model: str, indicates the variogram function model.
30 | :return: tuple, (x0,bnds). x0 represents the initial value of the parameters,
31 | and bnds represents the range of the parameters.
32 | '''
33 | if variogram_model == "linear":
34 | x0 = [(np.amax(y) - np.amin(y)) / 2 / (np.amax(h) - np.amin(h)), np.amin(y)]
35 | bnds = ([0.0, 0.0], [np.inf, np.amax(y)])
36 | elif variogram_model == "power":
37 | x0 = [(np.amax(y) - np.amin(y)) / (np.amax(h) - np.amin(h)), 1.0, np.amin(y)]
38 | bnds = ([0.0, 0.001, 0.0], [np.inf, 1.999, np.amax(y)])
39 | else:
40 | x0 = [(np.amax(y) - np.amin(y)) / 2, 0.5 * np.amax(h), np.amin(y)]
41 | bnds = ([0.0, 0.0, 0.0], [np.amax(y), np.amax(h), np.amax(y)])
42 | return x0, bnds
43 |
44 |
45 | class VariogramBuilder:
46 | '''
47 | VariogramBuilder class is used to build variogram function.
48 | '''
49 |
50 | def __init__(self, lags, model="spherical"):
51 | '''
52 | The VariogramBuilder is constructed with lags and string indicating the model.
53 |
54 | :param lags: array_like, a lag is [distance,semivariance].
55 | :param model: str, indicates the variogram function model.
56 | '''
57 | self.model = model
58 | self.lags = np.array(lags)
59 | x0, bnds = getX0AndBnds(self.lags[:, 0], self.lags[:, 1], model)
60 | res = least_squares(resident, x0, bounds=bnds, loss="huber",
61 | args=(self.lags[:, 0], self.lags[:, 1], variogramModel(model)))
62 | self.params = res.x
63 | self.mae = np.mean(res.fun)
64 |
65 | def showVariogram(self, axes=None):
66 | '''
67 | Plot variogram.
68 |
69 | :param axes: axes, if axes is set to None, plot on a new axes.
70 | :return: None.
71 | '''
72 | if axes is None:
73 | import matplotlib.pyplot as axes
74 | variogram = self.getVariogram()
75 | axes.scatter(self.lags[:, 0], self.lags[:, 1], alpha=0.5)
76 | max = np.max(self.lags[:, 0])
77 | X = np.arange(0, max, max / 100)
78 | Y = variogram(X)
79 | axes.plot(X, Y, alpha=0.5, color="red", label=self.model)
80 |
81 | def getVariogram(self):
82 | '''
83 | Get variogram function(closure function).
84 | :return: function.
85 | '''
86 | def variogram(h):
87 | return variogramModel(self.model)(h, *self.params)
88 | return variogram
89 |
90 |
91 | class NestVariogram:
92 | '''
93 | NestVariogram class is used to calculate the nesting variogram function value.
94 | A NestVariogram object is a functor.
95 | '''
96 |
97 | def __init__(self, variograms, unitVectors):
98 | '''
99 | The nested variational function object is constructed by
100 | using a number of unit vectors and variograms calculated
101 | from different directions.
102 |
103 | :param variograms: list, variogram functions.
104 | :param unitVectors: array_like, unit vectors corresponding to the direction.
105 | '''
106 | self.variograms = variograms
107 | self.unitVectors = unitVectors
108 |
109 | def __call__(self, vec):
110 | '''
111 | Calculate the value of the nesting variogram function.
112 |
113 | :param vec: array_like, vectors.
114 | :return: array_like, variogram function value.
115 | '''
116 | totalVar = 0
117 | for idx, unitVector in enumerate(self.unitVectors):
118 | h = np.abs(np.dot(vec, unitVector))
119 | var = self.variograms[idx](h)
120 | totalVar += var
121 | return totalVar
122 |
123 |
124 | def calculateOmnidirectionalVariogram2D(samples, partitionNum=8, leastPairNum=10, lagNum=20, lagInterval=None,
125 | lagTole=None, bandWidth=None, model=None):
126 | '''
127 | Calculating the omnidirectional variogram in two dimensions.
128 |
129 | :param samples: ndarray, array containing all sample points. The last column must be the properties.
130 | Each item is represented by [x,y,property].
131 |
132 | :param partitionNum: integer, indicates how many parts the angle range is divided into.
133 | :param leastPairNum: integer, at least lastPairNum lags need to be searched
134 | in one direction to fit the variogram function.
135 | :param lagNum: integer, number of lags to search.
136 | :param lagInterval: number, interval lags' distance.
137 | If lagInterval is set to None, then it is set to 0.75 times.
138 | the maximum vector modulus length divided by lagNum.
139 | :param lagTole: number, tolerance of lag's distance.
140 | If lagTole is set to None, then it is set to lagInterval/2.
141 | :param bandWidth: number, bandwidth used during search.
142 | If bandWidth is set to None, then it is set to the mean
143 | of the vector modulus length divided by 2.
144 | :param model: str, specify which variogram function model to use for the fit.
145 | If model is set to None, fitting will be attempted using all the variogram
146 | function models in the variogramModel module, and the best fit will be used.
147 | :return: tuple, (NestVariogram,variogramBuilders).
148 | NestVariogram is NestVariogram object,
149 | variogramBuilders is a list of VariogramBuilder objects corresponding to
150 | all variogram functions maintained within the NestVariogram object.
151 | '''
152 | vecs = calcVecs(samples, repeat=False)
153 | vars = 0.5 * vecs[:, 2] ** 2
154 | vecs = vecs[:, :2]
155 | azimuthStep = np.pi / partitionNum
156 | unitVectors = []
157 | azimuths = []
158 | for i in range(partitionNum):
159 | azimuth = (i + 0.5) * azimuthStep
160 | azimuths.append(azimuth)
161 | unitVectors.append([np.cos(azimuth), np.sin(azimuth)])
162 | unitVectors = np.array(unitVectors)
163 | azimuths = np.array(azimuths)
164 | norms = np.linalg.norm(vecs, axis=1) + EPS
165 | if bandWidth is None:
166 | bandWidth = norms.mean() / 2
167 | if lagInterval is None:
168 | lagInterval = norms.max() * 0.75 / lagNum
169 | if lagTole is None:
170 | lagTole = lagInterval / 2
171 | lagRanList = [[(i + 1) * lagInterval - lagTole, (i + 1) * lagInterval + lagTole] for i in range(lagNum)]
172 | bucket = [[[] for j in range(lagNum)] for i in range(partitionNum)]
173 | thetas = np.arctan2(vecs[:, 1], vecs[:, 0])
174 | thetas[thetas < 0] += np.pi
175 | indiceTheta = thetas // azimuthStep
176 | indiceTheta = indiceTheta.astype('int')
177 | for i in range(partitionNum):
178 | deltas = thetas - azimuths[i]
179 | bands = norms * deltas
180 | for j in range(lagNum):
181 | indice = np.where(
182 | ((indiceTheta == i) & (norms > lagRanList[j][0]) & (norms < lagRanList[j][1]) & (bands < bandWidth)))[0]
183 | bucket[i][j] = list(zip(norms[indice], vars[indice]))
184 | processedBucket = [[] for i in range(partitionNum)]
185 | searchedPairNumRecords = [[] for i in range(partitionNum)]
186 | for i in range(partitionNum):
187 | for j in range(lagNum):
188 | searchedPairNum = len(bucket[i][j])
189 | if searchedPairNum < 3:
190 | continue
191 | searchedPairNumRecords[i].append(searchedPairNum)
192 | lag = np.mean(bucket[i][j], axis=0)
193 | processedBucket[i].append(lag)
194 | lagsList = [None for i in range(partitionNum)]
195 | availableDir = []
196 | for i in range(partitionNum):
197 | if len(processedBucket[i]) > leastPairNum:
198 | lagsList[i] = processedBucket[i]
199 | availableDir.append(i)
200 | variogramBuilders = []
201 | if model is None:
202 | for lags in lagsList:
203 | if lags is None:
204 | continue
205 | minResident = float('+inf')
206 | best = None
207 | for key in VariogramModelMap:
208 | vb = VariogramBuilder(lags, key)
209 | if vb.mae < minResident:
210 | minResident = vb.mae
211 | best = vb
212 | variogramBuilders.append(best)
213 | else:
214 | for lags in lagsList:
215 | if lags is None:
216 | continue
217 | vb = VariogramBuilder(lags, model)
218 | variogramBuilders.append(vb)
219 | nestVariogram = NestVariogram([vb.getVariogram() for vb in variogramBuilders], unitVectors[availableDir])
220 | return nestVariogram, variogramBuilders
221 |
222 |
223 | def calculateOmnidirectionalVariogram3D(samples, partitionNum=[6, 6], leastPairNum=10, lagNum=20, lagInterval=None,
224 | lagTole=None, bandWidth=None, model=None):
225 | '''
226 | Calculating the omnidirectional variogram in three dimensions.
227 |
228 | :param samples: ndarray, array containing all sample points. The last column must be the properties.
229 | Each item is represented by [x,y,z,property].
230 | :param partitionNum: array_like,Indicates how many parts the angle range
231 | in horizontal and vertical directions is divided into.
232 | :param leastPairNum: integer, at least lastPairNum lags need to be searched
233 | in one direction to fit the variogram function.
234 | :param lagNum: integer, number of lags to search.
235 | :param lagInterval: number, interval lags' distance.
236 | If lagInterval is set to None, then it is set to 0.75 times.
237 | :param lagTole: number, tolerance of lag's distance.
238 | If lagTole is set to None, then it is set to lagInterval/2.
239 | :param bandWidth: number, bandwidth used during search.
240 | If bandWidth is set to None, then it is set to the mean
241 | of the vector modulus length divided by 2.
242 | :param model: str, specify which variogram function model to use for the fit.
243 | If model is set to None, fitting will be attempted using all the variogram
244 | function models in the variogramModel module, and the best fit will be used.
245 | :return: tuple, (NestVariogram,variogramBuilders).
246 | NestVariogram is NestVariogram object,
247 | variogramBuilders is a list of VariogramBuilder objects corresponding to
248 | all variogram functions maintained within the NestVariogram object.
249 | '''
250 | vecs = calcVecs(samples, repeat=False)
251 | vars = 0.5 * vecs[:, 3] ** 2
252 | vecs = vecs[:, :3]
253 | if type(partitionNum) != list:
254 | partitionNum = [partitionNum, partitionNum]
255 | azimuthStep = np.pi / partitionNum[0]
256 | azimuths = [(i + 0.5) * azimuthStep for i in range(partitionNum[0])]
257 | dipStep = np.pi / partitionNum[1]
258 | dips = [(i + 0.5) * dipStep for i in range(partitionNum[1])]
259 | unitVectors = []
260 | for i in range(partitionNum[0]):
261 | a = azimuths[i]
262 | for j in range(partitionNum[1]):
263 | b = dips[j]
264 | unitVectors.append([np.cos(a) * np.cos(b), np.sin(a) * np.cos(b), np.sin(b)])
265 | unitVectors = np.array(unitVectors)
266 | azimuths = np.array(azimuths)
267 | dips = np.array(dips)
268 | norms = np.linalg.norm(vecs, axis=1) + EPS
269 | if bandWidth is None:
270 | bandWidth = norms.mean() / 2
271 | if lagInterval is None:
272 | lagInterval = norms.max() * 0.75 / lagNum
273 | if lagTole is None:
274 | lagTole = lagInterval / 2
275 | lagRanList = [[(i + 1) * lagInterval - lagTole, (i + 1) * lagInterval + lagTole] for i in range(lagNum)]
276 | bucket = [[[[] for k in range(lagNum)] for j in range(partitionNum[1])] for i in range(partitionNum[0])]
277 | thetas1 = np.arctan2(vecs[:, 1], vecs[:, 0])
278 | thetas1[thetas1 < 0] += np.pi
279 | thetas2 = np.arctan2(vecs[:, 2], np.linalg.norm(vecs[:, :2], axis=1))
280 | thetas2[thetas2 < 0] += np.pi
281 | indiceTheta1 = thetas1 // azimuthStep
282 | indiceTheta1 = indiceTheta1.astype('int')
283 | indiceTheta2 = thetas2 // dipStep
284 | indiceTheta2 = indiceTheta2.astype('int')
285 | for i in range(partitionNum[0]):
286 | for j in range(partitionNum[1]):
287 | unitVector = unitVectors[i * partitionNum[1] + j]
288 | angles = np.arccos(np.dot(vecs, unitVector) / norms)
289 | indice = np.where(angles > np.pi / 2)[0]
290 | angles[indice] = np.pi - angles[indice]
291 | bands = norms * np.sin(angles)
292 | for k in range(lagNum):
293 | indice = np.where(
294 | ((indiceTheta1 == i) & (indiceTheta2 == j) & (norms > lagRanList[k][0]) & (
295 | norms < lagRanList[k][1]) & (bands < bandWidth)))[0]
296 | bucket[i][j][k] = list(zip(norms[indice], vars[indice]))
297 | processedBucket = [[[] for j in range(partitionNum[1])] for i in range(partitionNum[0])]
298 | searchedPairNumRecords = [[[] for j in range(partitionNum[1])] for i in range(partitionNum[0])]
299 | for i in range(partitionNum[0]):
300 | for j in range(partitionNum[1]):
301 | for k in range(lagNum):
302 | searchedPairNum = len(bucket[i][j][k])
303 | if searchedPairNum < 3:
304 | continue
305 | searchedPairNumRecords[i][j].append(searchedPairNum)
306 | lag = np.mean(bucket[i][j][k], axis=0)
307 | processedBucket[i][j].append(lag)
308 | lagsList = [None for i in range(partitionNum[0] * partitionNum[1])]
309 | availableDir = []
310 | for i in range(partitionNum[0]):
311 | for j in range(partitionNum[1]):
312 | if len(processedBucket[i][j]) > leastPairNum:
313 | idx = i * partitionNum[1] + j
314 | lagsList[idx] = processedBucket[i][j]
315 | availableDir.append(idx)
316 | variogramBuilders = []
317 | if model is None:
318 | for lags in lagsList:
319 | if lags is None:
320 | continue
321 | minResident = float('+inf')
322 | best = None
323 | for key in VariogramModelMap:
324 | vb = VariogramBuilder(lags, key)
325 | if vb.mae < minResident:
326 | minResident = vb.mae
327 | best = vb
328 | variogramBuilders.append(best)
329 | else:
330 | for lags in lagsList:
331 | if lags is None:
332 | continue
333 | vb = VariogramBuilder(lags, model)
334 | variogramBuilders.append(vb)
335 | nestVariogram = NestVariogram([vb.getVariogram() for vb in variogramBuilders], unitVectors[availableDir])
336 | return nestVariogram, variogramBuilders
337 |
338 |
339 | def calculateDefaultVariogram2D(samples, model='spherical'):
340 | '''
341 | Calculate the default variogram function in two dimensions,
342 | without considering the effect of direction.
343 |
344 | :param samples: ndarray, array containing all sample points. The last column must be the properties.
345 | Each item is represented by [x,y,property].
346 | :param model: str, specify which variogram function model to use for the fit.
347 | :return: VariogramBuilder object.
348 | '''
349 | vecs = calcVecs(samples, repeat=False)
350 | hav = calcHAVByVecs(vecs)
351 | lagNum = 20
352 | lagInterval = hav[:, 0].max() / 2 / lagNum
353 | lagTole = lagInterval * 0.5
354 | angles = hav[:, 1]
355 | buckets = []
356 | portionNum = 8
357 | portion = np.pi / portionNum
358 | for i in range(portionNum):
359 | count = np.where((angles > portion * i) & (angles < portion * (i + 1)))[0].shape[0]
360 | buckets.append(count)
361 | idx = np.argmax(buckets)
362 | angle = portion * idx
363 | angleTole = portion
364 | bandWidth = hav[:, 0].mean() / 2
365 | lags, _ = search2d(vecs[:, :2], hav[:, 2], lagNum, lagInterval, lagTole, angle, angleTole, bandWidth)
366 | if len(lags) < 3:
367 | lags = calcHV(samples)
368 | vb = VariogramBuilder(lags, model)
369 | return vb
370 |
371 |
372 | def calculateDefaultVariogram3D(samples, model='spherical'):
373 | '''
374 | Calculate the default variogram function in three dimensions,
375 | without considering the effect of direction.
376 |
377 | :param samples: ndarray, array containing all sample points. The last column must be the properties.
378 | Each item is represented by [x,y,z,property].
379 | :param model: str, specify which variogram function model to use for the fit.
380 | :return: VariogramBuilder object.
381 | '''
382 | vecs = calcVecs(samples, repeat=False)
383 | habv = calcHABVByVecs(vecs)
384 | lagNum = 20
385 | lagInterval = habv[:, 0].max() / 2 / lagNum
386 | lagTole = lagInterval * 0.5
387 | azimuths = habv[:, 1]
388 | dips = habv[:, 2]
389 | buckets = []
390 | portionNum = 5
391 | portion = np.pi / portionNum
392 | for i in range(portionNum):
393 | for j in range(portionNum):
394 | count = np.where((azimuths > portion * i) & (azimuths < portion * (i + 1)) & (dips > portion * j) & (
395 | dips < portion * (j + 1)))[0].shape[0]
396 | buckets.append(count)
397 | idx = np.argmax(buckets)
398 | azimuth = idx // portionNum * portion
399 | dip = idx % portionNum * portion
400 | angleTole = portion / 2
401 | bandWidth = habv[:, 0].mean() / 2
402 | lags, _ = search3d(vecs[:, :3], habv[:, 3], lagNum, lagInterval, lagTole, azimuth, dip, angleTole, bandWidth)
403 | if len(lags) < 3:
404 | lags = calcHV(samples)
405 | vb = VariogramBuilder(lags, model)
406 | return vb
407 |
--------------------------------------------------------------------------------
/src/tfinterpy/variogramExp.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 |
3 | EPS = 1e-16
4 |
5 | def search2d(vecs, vars, lagNum, lagInterval, lagTole, angle, angleTole, bandWidth):
6 | '''
7 | Search for lags in two dimensions.
8 |
9 | :param vecs: ndarray, vectors.
10 | :param vars: ndarray, semivariance.
11 | :param lagNum: integer, number of lags to search.
12 | :param lagInterval: number, interval lags' distance.
13 | :param lagTole: number, tolerance of lag's distance.
14 | :param angle: number, search direction, angle range is [0, PI].
15 | :param angleTole: number, angle tolerance.
16 | :param bandWidth: number, bandwidth used during search.
17 | :return: tuple, (processedLags, lags).
18 | processedLags is the mean-processed lags.
19 | lags is original searched lags.
20 | '''
21 | unitVector = np.array([np.cos(angle), np.sin(angle)])
22 | return searchLags(vecs, vars, lagNum, lagInterval, lagTole, unitVector, angleTole, bandWidth)
23 |
24 |
25 | def search3d(vecs, vars, lagNum, lagInterval, lagTole, azimuth, dip, angleTole, bandWidth):
26 | '''
27 |
28 | :param vecs: ndarray, vectors.
29 | :param vars: ndarray, semivariance.
30 | :param lagNum: integer, number of lags to search.
31 | :param lagInterval: number, interval lags' distance.
32 | :param lagTole: number, tolerance of lag's distance.
33 | :param azimuth: number, azimuth of search direction, the range of azimuth is [0, PI].
34 | :param dip: number, dip of search direction, the range of dip is [0, PI].
35 | :param angleTole: number, angle tolerance.
36 | :param bandWidth: number, bandwidth used during search.
37 | :return: tuple, (processedLags, lags).
38 | processedLags is the mean-processed lags.
39 | lags is original searched lags.
40 | '''
41 | unitVector = np.array([np.cos(azimuth) * np.cos(dip), np.sin(azimuth) * np.cos(dip), np.sin(dip)])
42 | return searchLags(vecs, vars, lagNum, lagInterval, lagTole, unitVector, angleTole, bandWidth)
43 |
44 |
45 | def searchLags(vecs, vars, lagNum, lagInterval, lagTole, unitVector, angleTole, bandWidth):
46 | '''
47 | Search lags.
48 |
49 | :param vecs: ndarray, vectors.
50 | :param vars: ndarray, semivariance.
51 | :param lagNum: integer, number of lags to search.
52 | :param lagInterval: number, interval lags' distance.
53 | :param lagTole: number, tolerance of lag's distance.
54 | :param unitVector: array_like, unit vector of search direction.
55 | :param angleTole: number, angle tolerance.
56 | :param bandWidth: number, bandwidth used during search.
57 | :return: tuple, (processedLags, lags).
58 | processedLags is the mean-processed lags.
59 | lags is original searched lags.
60 | '''
61 | norms = np.linalg.norm(vecs, axis=1) + EPS
62 | thetas = np.arccos(np.dot(vecs, unitVector) / norms)
63 | indice = np.where(thetas > np.pi / 2)[0]
64 | thetas[indice] = np.pi - thetas[indice]
65 | # filter with angle
66 | remain = np.where(thetas <= angleTole)[0]
67 | norms = norms[remain]
68 | thetas = thetas[remain]
69 | vars = vars[remain]
70 | # filter with bandwith
71 | bands = norms * np.sin(thetas)
72 | remain = np.where(bands <= bandWidth)[0]
73 | norms = norms[remain]
74 | vars = vars[remain]
75 | # filter with lag range
76 | lagRanList = []
77 | for i in range(1, lagNum + 1):
78 | lagRanList.append([lagInterval * i - lagTole, lagInterval * i + lagTole])
79 | lags = [[] for i in range(lagNum)]
80 | for i in range(len(norms)):
81 | h = norms[i]
82 | for j in range(len(lagRanList)):
83 | if h > lagRanList[j][0] and h < lagRanList[j][1]:
84 | lags[j].append([h, vars[i]])
85 | break
86 | processedLags = []
87 | for ls in lags:
88 | if len(ls)==0:
89 | continue
90 | mean = np.mean(ls, axis=0)
91 | if np.isnan(mean).any():
92 | continue
93 | processedLags.append(mean)
94 | return processedLags, lags
95 |
--------------------------------------------------------------------------------
/src/tfinterpy/variogramModel.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 |
3 |
4 | def linear(h, slope, C0):
5 | '''
6 | Linear model.
7 |
8 | :param h: number or ndarray, distance.
9 | :param slope: number.
10 | :param C0: number, nugget.
11 | :return: number or ndarray.
12 | '''
13 | return slope * h + C0
14 |
15 |
16 | def power(h, scale, exp, C0):
17 | '''
18 | Power model.
19 |
20 | :param h: number or ndarray, distance.
21 | :param scale: number.
22 | :param exp: number.
23 | :param C0: number, nugget.
24 | :return: number or ndarray.
25 | '''
26 | return scale * (h ** exp) + C0
27 |
28 |
29 | def gaussian(h, C, a, C0):
30 | '''
31 | Gaussian model.
32 |
33 | :param h: number or ndarray, distance.
34 | :param C: number, sill.
35 | :param a: number, range.
36 | :param C0: number, nugget.
37 | :return: number or ndarray.
38 | '''
39 | return C * (1.0 - np.exp(-(h ** 2.0) / (a * 4.0 / 7.0) ** 2.0)) + C0
40 |
41 |
42 | def exponent(h, C, a, C0):
43 | '''
44 | Exponent model.
45 |
46 | :param h: number or ndarray, distance.
47 | :param C: number, sill.
48 | :param a: number, range.
49 | :param C0: number, nugget.
50 | :return: number or ndarray.
51 | '''
52 | return C * (1.0 - np.exp(-h / (a / 3.0))) + C0
53 |
54 |
55 | def spherical(h, C, a, C0):
56 | '''
57 | Spherical model.
58 |
59 | :param h: number or ndarray, distance.
60 | :param C: number, sill.
61 | :param a: number, range.
62 | :param C0: number, nugget.
63 | :return: number or ndarray.
64 | '''
65 | return np.piecewise(h, [h <= a, h > a],
66 | [lambda x: C * ((3.0 * x) / (2.0 * a) - (x ** 3.0) / (2.0 * a ** 3.0)) + C0, C + C0, ])
67 |
68 |
69 | VariogramModelMap = {
70 | "spherical": spherical,
71 | "gaussian": gaussian,
72 | "exponent": exponent,
73 | "linear": linear,
74 | "power": power,
75 | }
76 |
77 |
78 | def variogramModel(name):
79 | '''
80 | Returns the variogram function based on the name.
81 |
82 | :param name: str, variogram function name.
83 | :return: function.
84 | '''
85 | func = VariogramModelMap.get(name)
86 | return func
87 |
--------------------------------------------------------------------------------
/src/tfinterpy/vtk/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # @Time : 2022/3/28 12:03
3 | # @Author : UCCU
4 |
--------------------------------------------------------------------------------
/src/tfinterpy/vtk/colorMap.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # @Time : 2022/3/25 20:05
3 | # @Author : UCCU
4 |
5 | import vtk
6 |
7 | CoolToWarm=[
8 | [0.0,[0,0,255]],
9 | [0.5,[255,255,255]],
10 | [1.0,[255,0,0]],
11 | ]
12 |
13 | Rainbow=[
14 | [0.0,[0,0,255]],
15 | [0.2,[0,127,255]],
16 | [0.4,[0,255,0]],
17 | [0.6,[255,255,0]],
18 | [0.8,[255,165,0]],
19 | [1.0,[255,0,0]]
20 | ]
21 |
22 | BlueGreenOrange=[
23 | [0.0,[205,228,248]],
24 | [0.33,[29,65,88]],
25 | [0.66,[221,218,153]],
26 | [1.0,[115,2,0]]
27 | ]
28 |
29 | def getCTF(scalarMin,scalarMax,stops):
30 | '''
31 | Get vtk color transfer function by scalarRange and stops.
32 |
33 | :param scalarMin: number.
34 | :param scalarMax: number.
35 | :param stops: list, each stop represented by [percentage,[r,g,b]].
36 | :return: vtkDiscretizableColorTransferFunction object.
37 | '''
38 | ctf=vtk.vtkDiscretizableColorTransferFunction()
39 | total=scalarMax-scalarMin
40 |
41 | for stop in stops:
42 | ctf.AddRGBPoint(scalarMin+total*stop[0],stop[1][0]/255.0,stop[1][1]/255.0,stop[1][2]/255.0)
43 | return ctf
--------------------------------------------------------------------------------
/src/tfinterpy/vtk/fileUtils.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # @Time : 2022/3/26 19:53
3 | # @Author : UCCU
4 |
5 | import vtk
6 |
7 | def saveVTKPoints(filePath,polyData):
8 | '''
9 | Save vtkPoints to file.
10 |
11 | :param filePath: str.
12 | :param polyData: vtkPolyData object.
13 | :return: None.
14 | '''
15 | writer=vtk.vtkPolyDataWriter()
16 | writer.SetFileName(filePath)
17 | writer.SetInputData(polyData)
18 | writer.Write()
19 |
20 | def saveVTKGrid(filePath,rectilinearGrid):
21 | '''
22 | Save vtkRectilinearGrid to file.
23 |
24 | :param filePath: str.
25 | :param rectilinearGrid: vtkRectilinearGrid object.
26 | :return: None.
27 | '''
28 | writer=vtk.vtkRectilinearGridWriter()
29 | writer.SetFileName(filePath)
30 | writer.SetInputData(rectilinearGrid)
31 | writer.SetWriteArrayMetaData(True)
32 | writer.Write()
--------------------------------------------------------------------------------
/src/tfinterpy/vtk/rendering.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # @Time : 2022/3/28 12:08
3 | # @Author : UCCU
4 | import vtk
5 | import tfinterpy.vtk.colorMap as CM
6 | import numpy as np
7 |
8 | def createPointsActor(x,y,z=0,scalar=None,scalarRange=None,colorMap=CM.BlueGreenOrange):
9 | '''
10 | Create vertices representing coordinate points based on the coordinate data.
11 |
12 | :param x: array_like, x coordinate data.
13 | :param y: array_like, y coordinate data.
14 | :param z: array_like, z coordinate data.
15 | If it is a two-dimensional space, z should be set to 0.
16 | :param scalar: array_like, properties.
17 | :param scalarRange: array_like, [scalarMin, scalarMax], properties' range.
18 | :param colorMap: list, refer to the colorMap in the vtk.colorMap module.
19 | :return: vtkActor object.
20 | '''
21 | points = vtk.vtkPoints()
22 | L=len(x)
23 | points.SetNumberOfPoints(L)
24 | if z==0:
25 | for i in range(L):
26 | points.SetPoint(i,x[i],y[i],0)
27 | else:
28 | for i in range(L):
29 | points.SetPoint(i,x[i],y[i],z[i])
30 | polyData = vtk.vtkPolyData()
31 | polyData.SetPoints(points)
32 | scalarRange=None
33 | if scalar is not None:
34 | scalarArr = vtk.vtkFloatArray()
35 | scalarArr.SetName("scalar")
36 | scalarArr.SetNumberOfComponents(1)
37 | scalarArr.SetNumberOfValues(L)
38 | for i in range(L):
39 | scalarArr.SetTuple1(i,scalar[i])
40 | polyData.GetPointData().AddArray(scalarArr)
41 | polyData.GetPointData().SetActiveScalars("scalar")
42 | if scalarRange is None:
43 | scalarRange=[scalar.min(),scalar.max()]
44 | vertexGlyphFilter = vtk.vtkVertexGlyphFilter()
45 | vertexGlyphFilter.AddInputData(polyData)
46 | mapper = vtk.vtkPolyDataMapper()
47 | mapper.SetInputConnection(vertexGlyphFilter.GetOutputPort())
48 | if scalarRange is not None:
49 | mapper.SetScalarRange(*scalarRange)
50 | ctf = CM.getCTF(scalarRange[0], scalarRange[1], colorMap)
51 | ctf.SetDiscretize(True)
52 | ctf.Build()
53 | mapper.SetLookupTable(ctf)
54 | actor = vtk.vtkActor()
55 | actor.SetMapper(mapper)
56 | actor.GetProperty().SetPointSize(5)
57 | return actor
58 |
59 | def createGridActor(nx,ny,nz,x,y,z,scalar=None,scalarRange=None,colorMap=CM.Rainbow):
60 | '''
61 | Create rectilinear grid based on the coordinate data.
62 |
63 | :param nx: integer, number of x coordinate.
64 | :param ny: integer, number of y coordinate.
65 | :param nz: integer, number of z coordinate.
66 | :param x: array_like, x coordinate data.
67 | :param y: array_like, y coordinate data.
68 | :param z: array_like, z coordinate data.
69 | :param scalar: array_like, properties.
70 | :param scalarRange: array_like, [scalarMin, scalarMax], properties' range.
71 | :param colorMap: list, refer to the colorMap in the vtk.colorMap module.
72 | :return: vtkActor object.
73 | '''
74 | rgrid = vtk.vtkRectilinearGrid()
75 | nz=1 if nz<=1 else nz
76 | z=[0] if nz==1 else z
77 | dim=[nx, ny, nz]
78 | rgrid.SetDimensions(dim)
79 | xcoords = vtk.vtkFloatArray()
80 | xcoords.SetNumberOfValues(dim[0])
81 | xcoords.SetNumberOfComponents(1)
82 | ycoords = vtk.vtkFloatArray()
83 | ycoords.SetNumberOfValues(dim[1])
84 | ycoords.SetNumberOfComponents(1)
85 | zcoords = vtk.vtkFloatArray()
86 | zcoords.SetNumberOfValues(dim[2])
87 | zcoords.SetNumberOfComponents(1)
88 | for idx, value in enumerate(x):
89 | xcoords.SetValue(idx, value)
90 | for idx, value in enumerate(y):
91 | ycoords.SetValue(idx, value)
92 | for idx, value in enumerate(z):
93 | zcoords.SetValue(idx, value)
94 | rgrid.SetXCoordinates(xcoords)
95 | rgrid.SetYCoordinates(ycoords)
96 | rgrid.SetZCoordinates(zcoords)
97 | if scalar is not None:
98 | scalarArr = vtk.vtkFloatArray()
99 | scalarArr.SetName('scalar')
100 | scalarArr.SetNumberOfComponents(1)
101 | scalarArr.SetNumberOfValues(len(scalar))
102 | for idx,value in enumerate(scalar):
103 | scalarArr.SetValue(idx,value)
104 | rgrid.GetPointData().AddArray(scalarArr)
105 | rgrid.GetPointData().SetActiveScalars("scalar")
106 | if scalarRange is None:
107 | scalarRange = [np.percentile(scalar,1), np.percentile(scalar,99)]
108 | mapper = vtk.vtkDataSetMapper()
109 | mapper.SetInputData(rgrid)
110 | if scalarRange is not None:
111 | mapper.SetScalarRange(*scalarRange)
112 | ctf = CM.getCTF(scalarRange[0], scalarRange[1], colorMap)
113 | ctf.SetDiscretize(True)
114 | ctf.Build()
115 | mapper.SetLookupTable(ctf)
116 | actor = vtk.vtkActor()
117 | actor.SetMapper(mapper)
118 | actor.GetProperty().SetInterpolationToGouraud()
119 | return actor
120 |
121 | def rendering(actor):
122 | '''
123 | Create a new render window to render the actor.
124 |
125 | :param actor: vtkActor object.
126 | :return: None.
127 | '''
128 | ren = vtk.vtkRenderer()
129 | ren.AddActor(actor)
130 | renWin = vtk.vtkRenderWindow()
131 | renWin.AddRenderer(ren)
132 | iren = vtk.vtkRenderWindowInteractor()
133 | iren.SetRenderWindow(renWin)
134 | ren.SetBackground(0.447, 0.552, 0.756)
135 | renWin.SetSize(960, 680)
136 | iren.Initialize()
137 | ren.ResetCamera()
138 | renWin.Render()
139 | iren.Start()
--------------------------------------------------------------------------------