2013-12-22 3 views
0

У меня есть данные 3D-измерения на сфере, которая очень грубая, и я хочу интерполировать. Я обнаружил, что RectSphereBivariateSpline из scipy.interpolate должен быть наиболее подходящим. я использовал пример в документации RectSphereBivariateSpline в качестве отправной точки и теперь имею следующий код:SciPy RectSphereBivariateSpline интерполяция над сферой, возвращающей ValueError

""" read csv input file, post process and plot 3D data """ 
import csv 
import numpy as np 
from mayavi import mlab 
from scipy.interpolate import RectSphereBivariateSpline 

# user input 
nElevationPoints = 17 # needs to correspond with csv file 
nAzimuthPoints = 40 # needs to correspond with csv file 
threshold = - 40 # needs to correspond with how measurement data was captured 
turnTableStepSize = 72 # needs to correspond with measurement settings 
resolution = 0.125 # needs to correspond with measurement settings 

# read data from file 
patternData = np.empty([nElevationPoints, nAzimuthPoints]) # empty buffer 
ifile = open('ttest.csv') # need the 'b' suffix to prevent blank rows being inserted 
reader = csv.reader(ifile,delimiter=',') 
reader.next() # skip first line in csv file as this is only text 
for nElevation in range (0,nElevationPoints): 
    # azimuth 
    for nAzimuth in range(0,nAzimuthPoints): 
     patternData[nElevation,nAzimuth] = reader.next()[2] 
ifile.close() 

# post process 
def r(thetaIndex,phiIndex): 
    """r(thetaIndex,phiIndex): function in 3D plotting to return positive vector length from patternData[theta,phi]""" 
    radius = -threshold + patternData[thetaIndex,phiIndex] 
    return radius 

#phi,theta = np.mgrid[0:nAzimuthPoints,0:nElevationPoints] 
theta = np.arange(0,nElevationPoints) 
phi = np.arange(0,nAzimuthPoints) 
thetaMesh, phiMesh = np.meshgrid(theta,phi) 
stepSizeRad = turnTableStepSize * resolution * np.pi/180 
theta = theta * stepSizeRad 
phi = phi * stepSizeRad 

# create new grid to interpolate on 
phiIndex = np.linspace(1,360,360) 
phiNew = phiIndex*np.pi/180 
thetaIndex = np.linspace(1,180,180) 
thetaNew = thetaIndex*np.pi/180 
thetaNew,phiNew = np.meshgrid(thetaNew,phiNew) 
# create interpolator object and interpolate 
data = r(thetaMesh,phiMesh) 
lut = RectSphereBivariateSpline(theta,phi,data.T) 
data_interp = lut.ev(thetaNew.ravel(),phiNew.ravel()).reshape((360,180)).T 

x = (data_interp(thetaIndex,phiIndex)*np.cos(phiNew)*np.sin(thetaNew)) 
y = (-data_interp(thetaIndex,phiIndex)*np.sin(phiNew)*np.sin(thetaNew)) 
z = (data_interp(thetaIndex,phiIndex)*np.cos(thetaNew)) 

# plot 3D data 
obj = mlab.mesh(x, y, z, colormap='jet') 
obj.enable_contours = True 
obj.contour.filled_contours = True 
obj.contour.number_of_contours = 20 
mlab.show() 

пример из документации работает, но когда я пытаюсь запустить приведенный выше код со следующими данными испытания: testdata Я получаю ValueError в позиции кода, где объявлен объект RectSphereBivariateSpline интерполятор:

ValueError: ERROR: on entry, the input data are controlled on validity the following restrictions must be satisfied. -1<=iopt(1)<=1, 0<=iopt(2)<=1, 0<=iopt(3)<=1, -1<=ider(1)<=1, 0<=ider(2)<=1, ider(2)=0 if iopt(2)=0. -1<=ider(3)<=1, 0<=ider(4)<=1, ider(4)=0 if iopt(3)=0. mu >= mumin (see above), mv >= 4, nuest >=8, nvest >= 8, kwrk>=5+mu+mv+nuest+nvest, lwrk >= 12+nuest*(mv+nvest+3)+nvest*24+4*mu+8*mv+max(nuest,mv+nvest) 0< u(i-1)=0: s>=0 if s=0: nuest>=mu+6+iopt(2)+iopt(3), nvest>=mv+7 if one of these conditions is found to be violated,control is immediately repassed to the calling program. in that case there is no approximation returned.

Я пытался и пытался, но я абсолютно невежественны, что я должен изменить, чтобы удовлетворить объект RectSphereBivariateSpline.

Есть ли у кого-нибудь намек на то, что я могу делать неправильно?

- EDIT - С предложениями от #HYRY, теперь у меня есть следующий код, который выполняется без ошибок во время выполнения:

""" read csv input file, post process and plot 3D data """ 
import csv 
import numpy as np 
from mayavi import mlab 
from scipy.interpolate import RectSphereBivariateSpline 

# user input 
nElevationPoints = 17 # needs to correspond with csv file 
nAzimuthPoints = 40 # needs to correspond with csv file 
threshold = - 40 # needs to correspond with how measurement data was captured 
turnTableStepSize = 72 # needs to correspond with measurement settings 
resolution = 0.125 # needs to correspond with measurement settings 

# read data from file 
patternData = np.empty([nElevationPoints, nAzimuthPoints]) # empty buffer 
ifile = open('ttest.csv') # need the 'b' suffix to prevent blank rows being inserted 
reader = csv.reader(ifile,delimiter=',') 
reader.next() # skip first line in csv file as this is only text 
for nElevation in range (0,nElevationPoints): 
    # azimuth 
    for nAzimuth in range(0,nAzimuthPoints): 
     patternData[nElevation,nAzimuth] = reader.next()[2] 
ifile.close() 

# post process 
def r(thetaIndex,phiIndex): 
    """r(thetaIndex,phiIndex): function in 3D plotting to return positive vector length from patternData[theta,phi]""" 
    radius = -threshold + patternData[thetaIndex,phiIndex] 
    return radius 

#phi,theta = np.mgrid[0:nAzimuthPoints,0:nElevationPoints] 
theta = np.arange(0,nElevationPoints) 
phi = np.arange(0,nAzimuthPoints) 
thetaMesh, phiMesh = np.meshgrid(theta,phi) 
stepSizeRad = turnTableStepSize * resolution * np.pi/180 
theta = theta * stepSizeRad 
phi = phi * stepSizeRad 

# create new grid to interpolate on 
phiIndex = np.arange(1,361) 
phiNew = phiIndex*np.pi/180 
thetaIndex = np.arange(1,181) 
thetaNew = thetaIndex*np.pi/180 
thetaNew,phiNew = np.meshgrid(thetaNew,phiNew) 
# create interpolator object and interpolate 
data = r(thetaMesh,phiMesh) 
theta[0] += 1e-6 # zero values for theta cause program to halt; phi makes no sense at theta=0 
lut = RectSphereBivariateSpline(theta,phi,data.T) 
data_interp = lut.ev(thetaNew.ravel(),phiNew.ravel()).reshape((360,180)).T 

def rInterp(theta,phi): 
    """rInterp(theta,phi): function in 3D plotting to return positive vector length from interpolated patternData[theta,phi]""" 
    thetaIndex = theta/(np.pi/180) 
    thetaIndex = thetaIndex.astype(int) 
    phiIndex = phi/(np.pi/180) 
    phiIndex = phiIndex.astype(int) 
    radius = data_interp[thetaIndex,phiIndex] 
    return radius 
# recreate mesh minus one, needed otherwise the below gives index error, but why?? 
phiIndex = np.arange(0,360) 
phiNew = phiIndex*np.pi/180 
thetaIndex = np.arange(0,180) 
thetaNew = thetaIndex*np.pi/180 
thetaNew,phiNew = np.meshgrid(thetaNew,phiNew) 

x = (rInterp(thetaNew,phiNew)*np.cos(phiNew)*np.sin(thetaNew)) 
y = (-rInterp(thetaNew,phiNew)*np.sin(phiNew)*np.sin(thetaNew)) 
z = (rInterp(thetaNew,phiNew)*np.cos(thetaNew)) 

# plot 3D data 
obj = mlab.mesh(x, y, z, colormap='jet') 
obj.enable_contours = True 
obj.contour.filled_contours = True 
obj.contour.number_of_contours = 20 
mlab.show() 

Однако сюжет сильно отличается от не-интерполированных данных, см. фото here как справка.

Кроме того, при запуске интерактивного сеанса data_interp намного больше по значению (> 3e5), чем исходные данные (это около 20 макс.).

Любые дополнительные советы?

ответ

1

Похоже, что theta[0] не может быть 0, если вы измените его Литт перед вызовом RectSphereBivariateSpline:

theta[0] += 1e-6 
+0

Отлично! Это решает вызов объекта интерполятора! Теперь я вижу, что у меня есть и другие проблемы для решения, но, надеюсь, я смогу самостоятельно их обработать. Не могли бы вы сообщить мне, как вы это поняли (чтобы я мог стать более самодостаточным)? – niels

+0

@ user3116919, я сравнил ваши данные с данными примера, единственное отличие в том, что ваши данные lats содержат ноль. И когда lat равен 0, у lons не будет никаких средств, поэтому я думаю, что это проблема. – HYRY

+0

Смарт! Еще раз спасибо. – niels

Смежные вопросы