2

I have a map of values for a specific grid:

X       Y       Z       Value
0.555   0.334   0.472   1.361
0.674   0.729   0.711   2.114
0.538   0.982   0.886   2.406
0.775   0.279   0.789   1.843
0.292   0.206   0.984   1.482

I would like to convert the values (using same kind of interpolation method) into a pre-existing grid:

X       Y       Z       NewValue    
0.721   0.824   0.974   
0.244   0.982   0.813   
0.239   0.288   0.961   
0.885   0.439   0.308   
0.344   0.006   0.554   

for example in 2D: the new values:

X       Y       Value
0.429   0.714   1.142
0.583   0.826   1.409
0.309   0.872   1.182
0.563   0.096   0.659
0.924   0.947   1.872

the old, pre-existing grid:

X       Y   
0.595   0.928   
0.426   0.800   
0.974   0.527   
0.864   0.398   
0.915   0.816   

the orange dots will be converted to the new blue dots.

enter image description here

Thanks in advance

umn
  • 431
  • 6
  • 17
  • What do you mean when you define your grid by those 3 columns of numbers? – zabop Jul 15 '20 at 09:15
  • hey, not fully understand your question. this grid define a 3D object. the 4th column is the value for each vertex (in my case: temperature for each coordinate). was I clear enough? – umn Jul 15 '20 at 09:53
  • I think I get you now, thanks! – zabop Jul 15 '20 at 12:17
  • Do you have code for the 2D case? – zabop Jul 15 '20 at 12:18
  • Since you have a mesh, connectivity, and node values, I'd recommend that you use FEA element interpolation to generate the internal temperature values. All you'd have to do is transform the global coordinate to the appropriate element local coordinates. Substitute the local coordinate into the shape functions and interpolate from the node temperatures. Linear shape functions for 3D hex elements are well known. – duffymo Jul 15 '20 at 16:16
  • @duffymo does he have connectivity? Of course it can be created e.g. as Delaunay triangulation.. – Jan Stránský Jul 17 '20 at 08:13
  • In my opinion, this question is about the method itself. The programming should be easy then. Base function interpolation is one option. Some weighted average using "hill" kernel functions is another approach. Putting values to the closest point (if the number of points on original and new mesh are the same, like in the examples provided) is another....... @umn How many points you have in a real case? Could you please describe more the actual use case and "physics/math behind"? – Jan Stránský Jul 17 '20 at 08:15

2 Answers2

0

OK found it.

First we need to make sure the the origins and/or the coordinates is the same.

Second,

import pandas
import numpy
import scipy

old_x = dfOld['X'].to_numpy()
old_y = dfOld['Y'].to_numpy()
old_z = dfOld['Z'].to_numpy()
oldValues = dfOld['Value'].to_numpy()

new_x = dfNew['x'].to_numpy()
new_y = dfNew['y'].to_numpy()
new_z = dfNew['z'].to_numpy()

dfLin = scipy.interpolate.griddata((old_x, old_y, old_z), oldValues, (new_x, new_y, new_z), method='linear')
dfNear = scipy.interpolate.griddata((old_x, old_y, old_z), oldValues, (new_x, new_y, new_z), method='nearest')
dfLin[numpy.isnan(dfLin)] = dfNear[numpy.isnan(dfLin)] 
final = np.concatenate([newGrid, dfLin], axis=1)
umn
  • 431
  • 6
  • 17
0

A good and easy way to interpolate is using radial basis functions. It works in 2 and 3 dimensions.

If you use Python and install a few modules like numpy, scipy and matplotlib (or use Anaconda instead, it carries all of them) then an implementation could look like this (not completely checked for correctness).

import numpy as np
from scipy.interpolate import Rbf
import matplotlib
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import pandas as pd
import matplotlib.cm as cm


# data read from csv files
source = 'source.csv'
target = 'target.csv'

# create a pandas dataframe for each file
# pandas used here so that a huge dataset can be handled easily
df = pd.read_csv(source, names=['xs', 'ys', 'zs', 'ts'])
df1 = pd.read_csv(target, names=['xt', 'yt', 'zt'])

# convert the data to numbers
xs = df['xs'].values
ys = df['ys'].values
zs = df['zs'].values
ts = df['ts'].values

xt = df1['xt'].values
yt = df1['yt'].values
zt = df1['zt'].values

# create a radial basis function interpolant
# works in 2D and 3D
rbf = Rbf(xs, ys, zs, ts)

# evaluate the interpolated function at the new locations
T = rbf(xt, yt, zt)

# plot the result
fig = plt.figure(figsize=(12, 8))
ax = fig.add_subplot(111, projection='3d')

# plot the newly interpolated points (bigger dots)
ax.scatter(xt, yt, zt, c=T, cmap=cm.jet, vmin=1.3, vmax=2.4, s=300)

# plot the original data (smaller dots)
ax.scatter(xs, ys, zs, c=ts, cmap=cm.jet, vmin=1.3, vmax=2.4, s=100)

ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')

plt.show()

enter image description here

chiefenne
  • 565
  • 2
  • 15
  • 30