I’m working with a 3D dataset in Python where some (x,y) points create frame-like structures, some of them with multiple z-values per (x,y) pair, which seems to lead to a problem with griddata.
The provided code produces the interpolation between 2 data sets as a working example, and then tries to interpolate 2 data sets, where one has multiple z values. The data and the interpolation are plotted for each case. I also provide an image with a marking, what seems to create the problem afaik.
How can I interpolate such data with griddata or is there another way?

Code contains part of the original (simulation) data.
import numpy as np
import matplotlib.pyplot as plt
from scipy.spatial import distance
from scipy.interpolate import griddata
from scipy.ndimage import gaussian_filter
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
from matplotlib.colors import Normalize
from matplotlib import cm
import matplotlib.tri as mtri
from scipy.interpolate import LinearNDInterpolator
x1 = np.array([
0, 0.08317108166803, 0.16393703317322, 0.24010197356808, 0.31189968667059,
0.37964309047995, 0.44362962064596, 0.50416941327588, 0.56154833462750, 0.61603270573008,
0.66785467575344, 0.71722870327800, 0.76434124363645, 0.80936126105512, 0.85243882934910,
0.89371020366228, 0.93330023252176, 0.97132031393031, 1.0078733278234, 1.04305186588065,
1.07694164659622, 1.10962198351184, 1.14116475234496, 1.17163490787683, 1.20109277181813,
1.22959493653164, 1.25719327772516, 1.28393541084346, 1.30986533211137, 1.33502459428484,
1.3594517119059, 1.38318253432743, 1.40625054167016, 1.428687092237, 1.45052182005806,
1.47178239513572, 1.4924946731886, 1.51268282564772, 1.53236959683959, 1.55157657215197,
1.5703240685486, 1.58863120287582, 1.60651600994447, 1.62399550071956, 1.64108576853907,
1.65780207082065, 1.67415889980995, 1.69017008507776, 1.70584884180465, 1.72120783285127,
1.73625905724844, 1.75101389043042, 1.76548311976239, 1.77967698639756, 1.79360519288652,
1.80727689980216, 1.8207008202846, 1.83388518878035, 1.84683777315861, 1.85956584789141,
1.87207616663999, 1.88437496210868, 1.89646789288332, 1.90835992552183, 1.92005539714572,
1.9315578245162, 1.94286977773435, 1.95399269320514, 1.96492669014037, 1.97567031873621,
1.98622026624029, 1.99657105652974, 2.00671480587649, 2.01664080378909, 2.02633512036696,
2.03578034488985, 2.04495553215686, 2.05383630364206, 2.0623951776226, 2.0706018164916,
2.07842481734728, 2.0858329876037, 2.09279775917234, 2.09929633971377, 2.10531538227125,
2.11085508513429, 2.11593338459342, 2.12058937638755, 2.12488319044411, 2.12889284005344,
2.13270923022591, 2.13642524129613
])
z1 = np.array([
28.6619989743589, 28.6049608580482, 28.5450559014246, 28.4794835365082, 28.4092022241029,
28.3350387336261, 28.2576380039013, 28.1775367384564, 28.0951654495223, 28.0108638015799,
27.9249204615456, 27.8375597971889, 27.7489735572062, 27.6593178994861, 27.5687237423079,
27.4773041964674, 27.385152945665, 27.2923533725037, 27.1989741902862, 27.1050785554844,
27.0107190614389, 26.9159392616942, 26.8207798998579, 26.7252795524418, 26.6294706791138,
26.5333790187747, 26.4370286448011, 26.3404423792824, 26.2436415876413, 26.1466433615791,
26.0494627200553, 25.9521139974702, 25.8546109832136, 25.7569659319296, 25.6591888403289,
25.5612891089313, 25.4632757574251, 25.3651575801692, 25.2669423848755, 25.168636129068,
25.0702443614344, 24.9717723691753, 24.8732252294088, 24.7746078436806, 24.6759249761952,
24.5771812831842, 24.4783811991822, 24.3795278208977, 24.2806239242195, 24.1816722476486,
24.082675412506, 23.9836359405196, 23.8845562687947, 23.7854387639056, 23.6862857298263,
23.5870993764416, 23.4878813512533, 23.3886330916743, 23.2893560024275, 23.1900514136945,
23.0907205842034, 22.9913647072391, 22.8919849096176, 22.792582243255, 22.6931576855678,
22.5937118769204, 22.4942453558146, 22.3947585791552, 22.2952518558259, 22.1957253129467,
22.0961789025235, 21.9966124171542, 21.8970253898987, 21.7974170708687, 21.6977864181452,
21.5981324310853, 21.4984538542985, 21.398749114135, 21.2990163991982, 21.1992542481573,
21.0994617682189, 20.9996381351822, 20.8997827371874, 20.799896002592, 20.6999792732694,
20.6000347502029, 20.5000657435458, 20.4000764848403, 20.3000713432661, 20.2000540343164,
20.1000287433225, 20
])
y1 = np.full(len(x1),1)
x2 = np.array([
0, 0.09970480868419, 0.19934990930324, 0.29892560671855, 0.39845053029212,
0.49791294847979, 0.59729126792395, 0.69654894215390, 0.79562230931157,
0.89441829468223, 0.99278184799703, 1.09041596346573, 1.18680564093363,
1.2811247216627, 1.37173821384615, 1.45615592046124, 1.53140709459726,
1.59481447147833, 1.64540118865725, 1.68420020117436, 1.7139567901805,
1.73739377080012, 1.75669514508293, 1.77341533375185, 1.78855241978336,
1.80270054725639, 1.81619925811863, 1.82923458834867, 1.84190868011591,
1.8542787909028, 1.86637895717989, 1.87823123253782, 1.8898513429009,
1.90125155489232, 1.91244211394041, 1.92343198232874, 1.93422925599876,
1.94484137307261, 1.95527523060825, 1.96553726952681, 1.97563352932633,
1.98556968830044, 1.99535109412568, 2.00498278811171, 2.01446952528177,
2.02381579222306, 2.03302582656997, 2.04210365316528, 2.05105308938297,
2.05987776623044, 2.06858114998522, 2.07716655334668, 2.08563714669058,
2.09399597192344, 2.1022459544216, 2.11038991079032, 2.11843055346434,
2.12637049464471, 2.13421224945851, 2.14195824744614, 2.14961083302462,
2.15717226465044, 2.16464472287464, 2.17203031834828, 2.17933109740207,
2.18654904729014, 2.19368610417827, 2.20074416242255, 2.20772507771543,
2.21463066429355, 2.2214626950629, 2.22822290393084, 2.23491298448034,
2.24153458547506, 2.24808930743357, 2.25457870003345, 2.26100425466765,
2.26736739519304, 2.27366947406393, 2.27991176845626, 2.28609547194039,
2.29222169050455, 2.29829141992375, 2.30430552303668, 2.31026470050494,
2.31616945318094, 2.32202003758885, 2.32781640900641, 2.33355814983544,
2.33924438051412, 2.3448736508916, 2.35044381228348, 2.3559518778997,
2.36139385612463, 2.36676455738366, 2.37205741259143, 2.37726426201264,
2.38237517331566, 2.38737831946074, 2.39225993069978, 2.39700436076639,
2.40159431859356, 2.40601130725183, 2.41023630806784, 2.4142507588751,
2.418037990112, 2.42158487083293, 2.42488372545427, 2.42793436504128,
2.43074593332474, 2.4333379706335, 2.43574001568792, 2.4379889754186,
2.44012113735539, 2.44214574160271
])
z2 = np.array([
30.0078688964104, 30.0065512265173, 30.0029356360187, 29.9976735322442,
29.9915262693748, 29.9844424862537, 29.9762659464609, 29.9667364364951,
29.9554600427241, 29.9419800400481, 29.9256478232344, 29.9054159211507,
29.8799561681087, 29.8476996253689, 29.8061730864421, 29.7532731986494,
29.6880451094337, 29.6112448542866, 29.5253946922475, 29.4335819554567,
29.3384411867613, 29.2415312959595, 29.1437049711797, 29.04539962879,
28.9468401079325, 28.8481308935213, 28.7493306654707, 28.6504694225423,
28.5515612207417, 28.4526148172972, 28.3536354145385, 28.2546261943038,
28.1555895272291, 28.0565273761794, 27.9574414945533, 27.8583335076939,
27.7592047062979, 27.6600561309973, 27.5608887508238, 27.4617034796921,
27.3625011864055, 27.2632827022544, 27.1640488269094, 27.0648003331593,
26.9655379708194, 26.866262470073, 26.7669745291472, 26.6676746328858,
26.5683632230419, 26.4690407437848, 26.3697076224236, 26.2703642715209,
26.171011090825, 26.0716484692661, 25.9722767866544, 25.8728964148864,
25.7735077188227, 25.6741110570318, 25.5747068020388, 25.4752952472731,
25.3758766209457, 25.2764511425401, 25.1770190239312, 25.077580470411,
24.978135681488, 24.8786848515835, 24.7792281708969, 24.6797658262875,
24.5802980016905, 24.4808248780774, 24.381346633632, 24.2818634440495,
24.1823754825859, 24.0828829198801, 23.9833859238618, 23.8838846597107,
23.7843792895138, 23.6848699718101, 23.5853568615186, 23.4858401098541,
23.3863198605794, 23.2867961336504, 23.1872689742316, 23.0877384678003,
22.9882046876333, 22.8886676931036, 22.7891275276662, 22.6895842161987,
22.5900377616683, 22.4904881410033, 22.3909353002525, 22.2913791491932,
22.1918194461756, 22.0922558825952, 21.9926883788735, 21.8931167722048,
21.7935407990426, 21.6939600883707, 21.5943741599893, 21.4947824294466,
21.395184222527, 21.2955788018895, 21.1959654064542, 21.0963434196656,
20.9967131851386, 20.8970742537356, 20.7974262724062, 20.6977693400472,
20.5981040167542, 20.4984312619284, 20.3987523065558, 20.2990684973495,
20.1993811617366, 20.099691467103, 20
])
y2 = np.full(len(x2),2)
x3 = np.array([
0, 0.106091997247487, 0.212282862868987, 0.318600341722176, 0.425123104761527,
0.531901352872626, 0.638980673349671, 0.746408888895399, 0.85423835573243,
0.962522013543275, 1.07131093710695, 1.18064439993891, 1.29054534660613,
1.40102082494537, 1.51205952335725, 1.62363164712265, 1.73568405272677,
1.84814589283292, 1.96093277164309, 2.07395098084042, 2.18706544796369,
2.30006049798178, 2.41251892919309, 2.52351045392648, 2.63096976610101,
2.73100121086301, 2.77148016441521, 2.78453458174498, 2.79186010794094,
2.79751816975908, 2.80236248394865, 2.80670132496914, 2.81067659404222,
2.81436810315714, 2.81782835677761, 2.81838473210957, 2.82109652791738,
2.82420427153188, 2.82717868109766, 2.83004342751941, 2.83281945446213,
2.83552519787279, 2.83817680575457, 2.84078819902162, 2.84337124785453,
2.84593589783908, 2.84849035993836, 2.85104128587469, 2.85359396537556,
2.85615250287907, 2.85872000627528, 2.86129873724824, 2.86389026304064,
2.86649557135293, 2.86911518641933, 2.8717492484006, 2.87439759958004,
2.87705983816952, 2.87973537526801, 2.88242347197052, 2.88512327706806,
2.88783385231766, 2.88845703622116, 2.89055419723002, 2.89328326484414,
2.89601997738632, 2.89876323695298, 2.90151193463858, 2.90426495815636,
2.90702119863042, 2.90977955571619, 2.91253894330014, 2.91529829288703,
2.91805655711182, 2.92081271230053, 2.92356576021251, 2.92631472933472,
2.92905867580467, 2.93179668334584, 2.93452786251032, 2.93725134958514,
2.93965292016822, 2.93996630533669, 2.94267191310587, 2.94536737736262,
2.94805192150669, 2.95072478659992, 2.95338522921948, 2.9560325199586,
2.95866594104728, 2.96128478419988, 2.96388834746919, 2.96647593163284,
2.96904683568692, 2.97160035145282, 2.97413575724706, 2.97425125556441,
2.97665231021929, 2.97914923756346, 2.98162572566976, 2.98408090824307,
2.98651385151949, 2.98892353757412, 2.99130884415201, 2.99366851923393,
2.99600114768388, 2.9962606601005, 2.99830510879971, 3.00057851901249,
3.00281914620488, 3.00502428120326, 3.00719053828585, 3.00931351650196,
3.00952011645174, 3.01138721018009, 3.0134029388599, 3.01534737564675,
3.01699921085196, 3.01719889804888, 3.01892089400833, 3.02044973125651,
3.02078939388317, 3.02167377283328, 3.02228920892799, 3.02239824880744
])
z3 = np.array([
30.1186241174416, 30.1184849219899, 30.1171034471136, 30.1152951272103, 30.1133655615441,
30.1113195993005, 30.1091433108655, 30.1068210776114, 30.1043270725803, 30.1016326866963,
30.0986949871154, 30.095463219881, 30.091866695563, 30.087823561571, 30.0832240264785,
30.0779411584852, 30.0718042824719, 30.064598064254, 30.0560271138372, 30.0456642379577,
30.0328664792409, 30.0166381634173, 29.995383512023, 29.9666311419869, 29.9269062544625,
29.8724446142301, 20, 20.0992866487574, 20.1987778658839, 20.2983155533319, 20.3978803414887,
20.4974615256815, 20.5970538814448, 20.6966543922422, 20.796260963899, 29.8010645620936,
20.8958720196992, 20.9954865830927, 21.0951039613303, 21.1947236485541, 21.2943452750121,
21.3939685837807, 21.493593496968, 21.5932201164118, 21.6928485704969, 21.7924790313127,
21.8921116969745, 21.9917467869875, 22.0913845424964, 22.1910252330904, 22.2906691240923,
22.3903164843267, 22.4899675841224, 22.5896226941457, 22.6892820856006, 22.7889460266206,
22.888614783746, 22.988288620861, 23.0879678014928, 23.1876525873797, 23.287343240002,
23.3870400197103, 29.7142868959217, 23.486743187404, 23.5864530033367, 23.6861697290352,
23.7858936263979, 23.885624958565, 23.9853639878029, 24.0851109788725, 24.1848661985415,
24.2846299172733, 24.3844024085183, 24.4841839497909, 24.5839748236319, 24.6837753181654,
24.7835857287758, 24.8834063591202, 24.9832375223667, 25.0830795430067, 25.1829327578276,
29.6171448515155, 25.2827975190689, 25.3826741941813, 25.4825631716602, 25.5824648589361,
25.6823796912861, 25.7823081276471, 25.8822506637417, 25.9822078278468, 26.0821801933113,
26.1821683788585, 26.2821730607998, 26.3821949758609, 26.482234934283, 26.5822938276285,
29.5148759694037, 26.6823726493158, 26.7824724970099, 26.8825946040959, 26.9827403478161,
27.0829112850487, 27.1831091758242, 27.283336026885, 27.3835941282532, 27.4838861281617,
29.4108704451581, 27.5842150845333, 27.6845846449453, 27.7849990464475, 27.8854632367103,
27.9859831360428, 28.0865659498792, 29.3067361736195, 28.1872205245328, 28.2879579643369,
28.3887923780716, 29.2030641097122, 28.4897421297855, 28.5908314496745, 28.6920929845482,
29.0999759013086, 28.7935707828626, 28.997430828688, 28.8953250739844
])
y3 = np.full(len(x3),3)
def filter_data_by_indices(data, indices_to_keep):
# Convert 1-based indices to 0-based indices for Python indexing
indices_to_keep = [i - 1 for i in indices_to_keep]
# Filter the data by the specified indices
filtered_data = [data[i] for i in indices_to_keep if 0 <= i < len(data)]
return filtered_data
def mirror_data(data):
mirrored_data = []
for x,y,z in data:
# Combine positive and negative r values
x_combined = np.concatenate([-x[::-1], x])
z_combined = np.concatenate( [z[::-1], z ])-20 #offset of sim raw data
y_combined = np.full_like(x_combined, y[0])
mirrored_data.append((x_combined, y_combined, z_combined))
return mirrored_data
def nearest_neighbor_sort(data):
sorted_data = []
for x, y, z in data:
# Stack x and z to form (x, z) pairs
xz_pairs = np.column_stack((x, z))
# Nearest neighbor sorting
sorted_indices = [0] # Start with the first point
remaining_indices = list(range(1, len(xz_pairs)))
while remaining_indices:
last_index = sorted_indices[-1]
distances = [
distance.euclidean(xz_pairs[last_index], xz_pairs[i]) for i in remaining_indices
]
nearest_index = remaining_indices[np.argmin(distances)]
sorted_indices.append(nearest_index)
remaining_indices.remove(nearest_index)
# Apply the sorted indices to x and z, y remains unchanged
x_sorted = x[sorted_indices]
z_sorted = z[sorted_indices]
sorted_data.append((x_sorted, y, z_sorted))
return sorted_data
def plot_data(filtered_data):
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
all_x, all_y, all_z = [], [], []
for x, y, z in filtered_data:
# log_t = np.log10(t)
all_x.extend(x)
all_y.extend(y)
all_z.extend(z)
ax.plot(x, y, z, color='black', alpha=0.8, linewidth=1.5)
plt.show()
# Interpolate surface
X, Y, Z = interpolate_surface(all_x, all_y, all_z)
X_flat, Y_flat, Z_flat = X.flatten(), Y.flatten(), Z.flatten()
triangles = mtri.Triangulation(X_flat, Y_flat)
norm = Normalize(vmin=min(Y_flat), vmax=max(Y_flat))
cmap = cm.gnuplot
colors = cmap(norm(Y_flat))
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
# Build Poly3DCollection
poly3d = []
for tri in triangles.triangles:
poly3d.append([(X_flat[tri[0]], Y_flat[tri[0]], Z_flat[tri[0]]),
(X_flat[tri[1]], Y_flat[tri[1]], Z_flat[tri[1]]),
(X_flat[tri[2]], Y_flat[tri[2]], Z_flat[tri[2]])])
poly_collection = Poly3DCollection(poly3d, facecolors=colors[triangles.triangles].mean(axis=1),
edgecolors='black', linewidths=0.06, alpha=1)
ax.add_collection3d(poly_collection)
plt.show()
def interpolate_surface(all_r, all_log_t, all_z, num_points=100, sigma=1):
r_vals = np.linspace(min(all_r), max(all_r), num_points)
t_vals = np.linspace(min(all_log_t), max(all_log_t), num_points)
R, T = np.meshgrid(r_vals, t_vals)
points = np.vstack((all_r, all_log_t)).T
values = np.array(all_z)
Z = griddata(points, values, (R, T), method='linear') # 'cubic' or 'nearest'
## Interpolate the data with linearNDInterpolator
# interpolator = LinearNDInterpolator(points, values)
# Z = interpolator(np.array([R.flatten(), T.flatten()]).T).reshape(R.shape)
Z = np.nan_to_num(Z, nan=0)
# Z = gaussian_filter(Z, sigma=sigma)
return R, T, Z
data = [(x1,y1,z1),(x2,y2,z2),(x3,y3,z3)]
# plot first 2 data sets
filtered_data = filter_data_by_indices(data, [1,2])
sorted_data = nearest_neighbor_sort(filtered_data)
mirrored_data = mirror_data(sorted_data)
plot_data(mirrored_data)
# plot last 2 data sets (here interpolation is wrong)
filtered_data = filter_data_by_indices(data, [2,3])
sorted_data = nearest_neighbor_sort(filtered_data)
mirrored_data = mirror_data(sorted_data)
plot_data(mirrored_data)
