forked from jasonfleming/pputils
-
Notifications
You must be signed in to change notification settings - Fork 0
/
interp_from_pts.py
executable file
·145 lines (129 loc) · 4.36 KB
/
interp_from_pts.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#!/usr/bin/env python3
#
#+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!
# #
# interp_from_pts.py #
# #
#+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!+!
#
# Author: Pat Prodanovic, Ph.D., P.Eng.
#
# Date: May 26, 2016
#
# Purpose: Script takes in a xyz points file and a mesh file (in ADCIRC
# format), and interpolates the nodes of the mesh file from the points
# file. It uses scipy's kdtree to assign to the mesh node the point in
# the xyz dataset that is closest.
#
# Revised: May 27, 2016
# Made it such that a number of scipy neighbours is an input argument. If
# closest node is wanted, just use 1 neighbour. Note that this interpolation
# script is good only when data points file is very dense.
#
# Revised: Nov 13, 2016
# Fixed a division by zero error if the distance is exactly zero in the
# kdTree algorithm.
#
# Revised: Nov 21, 2016
# Changed KDTree to cKDTree to improve performance.
#
# Uses: Python 2 or 3, Matplotlib, Numpy
#
# Example:
#
# python interp_from_pts.py -p points.csv -m mesh.grd -o mesh_interp.grd -n 10
# where:
# -p xyz points file, no headers, comma delimited
# -m mesh (whose nodes are to be interpolated)
# -o interpolated mesh
#
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Global Imports
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
import os,sys # system parameters
import numpy as np # numpy
from scipy import spatial # scipy to get kdTree
from ppmodules.readMesh import * # to get all readMesh functions
from progressbar import ProgressBar, Bar, Percentage, ETA
#
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# MAIN
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
curdir = os.getcwd()
#
# I/O
if len(sys.argv) != 9 :
print('Wrong number of Arguments, stopping now...')
print('Usage:')
print('python interp_from_pts.py -p points.csv -m mesh.grd -o mesh_interp.grd -n 10')
sys.exit()
pts_file = sys.argv[2]
mesh_file = sys.argv[4]
output_file = sys.argv[6] # interp_mesh
neigh = int(sys.argv[8]) # the number of nearest neighbours
# I am imposing a limit on neigh to be between 1 and 10
if ((neigh < 1) or (neigh > 10)):
print('Number of neighbours must be between 1 and 10. Exiting.')
sys.exit(0)
print('Reading input data')
# read the points file
pts_data = np.loadtxt(pts_file, delimiter=',',skiprows=0,unpack=True)
x = pts_data[0,:]
y = pts_data[1,:]
z = pts_data[2,:]
# read the adcirc mesh file (_m is for mesh)
# this one has z values that are all zeros
m_n,m_e,m_x,m_y,m_z,m_ikle = readAdcirc(mesh_file)
print('Constructing KDTree object')
# to create a KDTree object
source = np.column_stack((x,y))
tree = spatial.cKDTree(source)
den = 0.0
tmp_sum = 0.0
print('Interpolating')
w = [Percentage(), Bar(), ETA()]
pbar = ProgressBar(widgets=w, maxval=m_n).start()
for i in range(m_n):
d,idx = tree.query((m_x[i],m_y[i]), k = neigh)
# calculate the denominator
if neigh > 1:
for j in range(neigh):
if (d[j] < 1.0E-6):
d[j] = 1.0E-6
den = den + (1.0 / (d[j]**2))
else:
if (d < 1.0E-6):
d = 1.0E-6
den = den + (1.0 / (d**2))
# calculate the weights
weights = (1.0 / d**2) / den
# to assign the interpolated value
if neigh > 1:
for j in range(neigh):
tmp_sum = tmp_sum + weights[j]*z[idx[j]]
else:
tmp_sum = weights * z[idx]
# now assign the value
m_z[i] = tmp_sum
# reset the denominator
den = 0.0
tmp_sum = 0.0
pbar.update(i+1)
pbar.finish()
print('Writing results to file')
# to create the output file (this is the interpolated mesh)
fout = open(output_file,"w")
# now to write the adcirc mesh file
fout.write("ADCIRC" + "\n")
# writes the number of elements and number of nodes in the header file
fout.write(str(m_e) + " " + str(m_n) + "\n")
# writes the nodes
for i in range(0,m_n):
fout.write(str(i+1) + " " + str("{:.3f}".format(m_x[i])) + " " +
str("{:.3f}".format(m_y[i])) + " " + str("{:.3f}".format(m_z[i])) + "\n")
#
# writes the elements
for i in range(0,m_e):
fout.write(str(i+1) + " 3 " + str(m_ikle[i,0]+1) + " " + str(m_ikle[i,1]+1) + " " +
str(m_ikle[i,2]+1) + "\n")
print('All done!')