简体   繁体   中英

Python: How to interpolate angles on a grid?

I have a grid with some given data. This data is given by its angle (from 0 to π ). Within this grid I have another smaller grid.

This might look like this:

在此处输入图片说明

Now I want to interpolate the angles on that grid.

I tried this by using scipy.interpolate.griddata what gives a good result. But there is a problem when the angles change from almost 0 to almost π (because the middle is π/2 ...)

Here is the result and it is easy to see what's going wrong.

在此处输入图片说明

How can I deal with that problem? Thank you! :)

Here is the code to reproduce:

import numpy as np
from matplotlib import pyplot as plt
from scipy.interpolate import griddata

ax = plt.subplot()
ax.set_aspect(1)

# Simulate some given data.
x, y = np.meshgrid(np.linspace(-10, 10, 20), np.linspace(-10, 10, 20))
data = np.arctan(y / 10) % np.pi
u = np.cos(data)
v = np.sin(data)

ax.quiver(x, y, u, v, headlength=0.01, headaxislength=0, pivot='middle', units='xy')

# Create a smaller grid within.
x1, y1 = np.meshgrid(np.linspace(-1, 5, 15), np.linspace(-6, 2, 20))
# ax.plot(x1, y1, '.', color='red', markersize=2)

# Interpolate data on grid.
interpolation = griddata((x.flatten(), y.flatten()), data.flatten(), (x1.flatten(), y1.flatten()))
u1 = np.cos(interpolation)
v1 = np.sin(interpolation)
ax.quiver(x1, y1, u1, v1, headlength=0.01, headaxislength=0, pivot='middle', units='xy',
          color='red', scale=3, width=0.03)

plt.show()

Edit:

Thanks to @bubble, there is a way to adjust the given angles before interpolation such that the result will be as desired. Therefore:

  1. Define a rectifying function:

     def RectifyData(data): for j in range(len(data)): step = data[j] - data[j - 1] if abs(step) > np.pi / 2: data[j] += np.pi * (2 * (step < 0) - 1) return data 
  2. Interpolate as follows:

     interpolation = griddata((x.flatten(), y.flatten()), RectifyData(data.flatten()), (x1.flatten(), y1.flatten())) u1 = np.cos(interpolation) v1 = np.sin(interpolation) 

I tried direct interpolation of cos(angle) and sin(angle) values, but this still yielded to discontinues, that cause wrong line directions. The main idea consist in reducing discontinues, eg [2.99,3.01, 0.05,0.06] should be transformed to something like this: [2.99, 3.01, pi+0.05, pi+0.06] . This is needed to apply 2D interpolation algorithm correctly. Almost the same problem raises in the following post .

def get_rectified_angles(u, v):
    angles = np.arcsin(v)
    inds = u < 0
    angles[inds] *= -1
# Direct approach of removing discontinues 
#     for j in range(len(angles[1:])):  
#         if abs(angles[j] - angles[j - 1]) > np.pi / 2:
#             sel = [abs(angles[j] + np.pi - angles[j - 1]), abs(angles[j] - np.pi - angles[j-1])]
#             if np.argmin(sel) == 0:
#                 angles[j] += np.pi
#             else:
#                 angles[j] -= np.pi
    return angles


ax.quiver(x, y, u, v, headlength=0.01, headaxislength=0, pivot='middle', units='xy')

# # Create a smaller grid within.
x1, y1 = np.meshgrid(np.linspace(-1, 5, 15), np.linspace(-6, 2, 20))

angles = get_rectified_angles(u.flatten(), v.flatten())

interpolation = griddata((x.flatten(), y.flatten()), angles, (x1.flatten(), y1.flatten()))
u1 = np.cos(interpolation)
v1 = np.sin(interpolation)
ax.quiver(x1, y1, u1, v1, headlength=0.01, headaxislength=0, pivot='middle', units='xy',
          color='red', scale=3, width=0.03)

Probably, numpy.unwrap function could be used to fix discontinues. In case of 1d data, numpy.interp has keyword period to handle periodic data.

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM