오늘은 IDL에서 내삽(Interpolation)에 사용되는 INTERPOLATE라는 함수를 이용하여 2차원 격자 데이터 기반의 내삽을 수행하는 예제를 소개해보고자 합니다. 내삽이라는 작업은 데이터 처리 분야에서 매우 자주 하는 일이기 때문에 IDL에서도 관련 함수들이 다양하게 지원되고 있습니다. 그런데 내삽도 여러가지 경우들이 있어서 그 때마다 적정한 함수를 사용해야 합니다. 제가 이 블로그에서 전에 소개했던 GRIDDATA, SPH_SCAT, TRIANGULATE 등은 주로 불규칙 분포를 하는 데이터 포인트들을 기반으로 내삽을 수행하는 내장함수들이었습니다. 반면 규칙적인 분포를 하는 데이터 포인트들을 기반으로 하는 내삽에 사용 가능한 INTERPOL, INTERPOLATE, BILINEAR 등과 같은 내장함수들도 따로 있습니다. 이들 중 오늘은 INTERPOLATE 함수에 촛점을 맞추려고 합니다.
방금 언급한 세 내장함수들 중 INTERPOL 함수는 1차원 데이터에 대한 내삽을 위한 전용 함수입니다. 그리고 BILINEAR 함수는 이름 그대로 2차원 격자 데이터 기반의 내삽을 위한 전용 함수입니다. 그리고 INTERPOLATE 함수는 1차원, 2차원, 3차원 격자 데이터에 대한 내삽이 모두 가능한 함수입니다. 그런데 오직 제 경험에 의하여 주관적으로 말씀드리자면, 1차원 데이터 내삽을 할 때에는 INTERPOL 함수를 사용하는 것이 좋고, 2차원 데이터일 경우에는 BILINEAR 함수보다는 그냥 INTERPOLATE 함수를 사용하는 것이 더 효율적인 것 같습니다. 물론 3차원 데이터일 경우에는 INTERPOLATE 함수 외에 다른 대안은 없을 겁니다. 어쨌든 오늘은 2차원 규칙 격자 데이터가주어진 상태에서 임의의 지점에 대한 내삽값을 INTERPOLATE 함수를 사용하여 산출하는 과정을 소개하겠습니다. 먼저 예제로 사용할 가상의 2차원 데이터를 다음과 같이 만들어봅시다.
data = HANNING(10, 10)*100
PRINT, MIN(data), MAX(data)
이 데이터는 10x10의 격자 구조를 갖고 있으며, 데이터값의 범위는 0~100입니다. 그 모습을 눈으로 보기 위하여 다음과 같이 IMAGE 함수를 사용하여 표출해봅시다.
win1 = WINDOW(DIMENSIONS=[600, 600], /NO_TOOLBAR)
im1 = IMAGE(data, RGB_TABLE=58, AXIS_STYLE=2, $
XTICKINTERVAL=1, YTICKINTERVAL=1, $
XMINOR=0, YMINOR=0, MARGIN=0.1, /CURRENT)
표출된 모습은 다음 그림과 같습니다. 어차피 제가 이 블로그에서 자주 사용해왔던 2차원 예제 데이터들과 같습니다.
일단 여기서 우리가 염두에 둬야 할 것은 격자점들의 위치 좌표값들입니다. 먼저 X축 방향으로 보면 10개의 격자점이 있으며 그 좌표값들은 0, 1, 2, ~~~, 8, 9입니다. Y축 방향도 마찬가지입니다. 그러면 임의의 지점에 대하여 내삽값을 한번 구해봅시다. 임의의 지점의 좌표는 다음과 같이 설정하였습니다.
xp = 6.5
yp = 3.8
즉 X좌표가 6.5이고 Y좌표가 3.8인 지점에 대한 내삽값을 얻고자 합니다. 이 위치를 다음과 같이 SYMBOL 함수를 사용하여 이미지 상에 표시해보면 다음과 같습니다.
sym1 = SYMBOL(xp, yp, 'circle', SYM_THICK=2, /DATA)
그리고 내삽값은 앞서 언급했던 INTERPOLATE 함수를 다음과 같이 사용하면 바로 구할 수 있습니다.
result = INTERPOLATE(data, xp, yp)
PRINT, result
INTERPOLATE 함수에서는 원본 2차원 데이터 배열이 첫 인자로 투입되고, 이어서 내삽할 지점 좌표값들이 순서대로 투입되면 됩니다. 실제로 출력된 내삽값은 66.6097로 나옵니다. 내삽에 사용된 알고리즘은 Bilinear Interpolation입니다. 내삽할 지점들이 하나가 아닌 여러 개일 경우에는 xp, yp를 배열의 형태로 바꿔주기만 하면 됩니다. 나머지 과정들은 그대로 두면 됩니다.
xp = [6.5, 3.4, 5.65]
yp = [3.8, 2.85, 6.15]
그러면 다음과 같은 세 개의 지점들에 대한 내삽값들이 산출됩니다.
산출된 내삽값들은 다음과 같습니다.
66.6097 45.8859 81.3194
그래서 INTERPOLATE 함수를 이용한 내삽은 이와 같이 꽤 간단합니다. 그런데 우리가 접하게 되는 실전 2차원 데이터들의 경우에는 좌표값들이 따로 주어지는 경우들이 종종 있습니다. 예를 들면 X축 방향은 경도(Longitude)이고 Y축 방향은 위도(Latitude)인 경우가 가장 흔합니다. 그래서 이번에는 이런 경우도 한번 살펴보겠습니다. 일단 2차원 데이터는 앞서 사용했던 그대로입니다. 다만 다음과 같이 X축 및 Y축 방향의 격자 좌표값 배열도 x, y라는 이름으로 함께 생성하였습니다.
data = HANNING(10, 10)*100
PRINT, MIN(data), MAX(data)
x = FINDGEN(10)*2+120
y = FINDGEN(10)*2+30
여기서는 격자점들의 위치가 X축 경도 방향으로는 120~138이며 간격이 2입니다. 그리고 Y축 위도 방향으로는 30~48이며 간격이 2입니다. 이 모습을 IMAGE 함수를 사용하여 별도의 그래픽 창에 다음과 같이 표출해봅시다.
win2 = WINDOW(DIMENSIONS=[600, 600], /NO_TOOLBAR)
im2 = IMAGE(data, x, y, RGB_TABLE=58, AXIS_STYLE=2, $
XTICKINTERVAL=2, YTICKINTERVAL=2, $
XMINOR=0, YMINOR=0, MARGIN=0.1, /CURRENT)
이전의 예제에서는 IMAGE 함수의 핵심 인자가 data뿐이었지만 이번에는 data, x, y가 함께 투입되었다는 점을 주목해야 합니다. 이렇게 하면 표출된 모습은 다음과 같습니다.
그림만 보면 이전의 예제와 비슷해 보이지만, X 및 Y축의 눈금값들이 이전과 달라졌음을 알 수 있습니다. 그러면 이번에도 특정 지점에 대한 내삽값을 구해봅시다. 지점의 좌표는 이제는 경도 및 위도로 주어져야 하겠지요. 경위도 좌표를 다음과 같이 가정해봅시다.
xp = 133.0
yp = 37.6
sym2 = SYMBOL(xp, yp, 'circle', SYM_THICK=2, /DATA)
이 위치를 이미지 상에 심볼로 표시해보면 다음 그림과 같습니다.
그러면 이 지점에 대한 내삽값을 다음과 같이 구해봅시다.
result = INTERPOLATE(data, xp, yp)
PRINT, result
그런데 출력된 내삽값을 확인해보면 약 0.912 정도인 것으로 나옵니다. 이 값은 과연 타당한 값일까요? 사실 지점의 위치를 그림에서 보면 우리가 앞서 봤던 예제의 경우와 상대적 위치가 거의 같습니다. 좌표값 자체만 달라졌을 뿐입니다. 사실 이번 예제에서도 이 지점에 대한 내삽값은 앞서 우리가 얻었던 66.6097과 거의 유사한 값이 나와야 맞습니다. 하지만 이렇게 0.912와 같은 엉뚱한 값이 나온 이유는, 우리가 x 및 y 배열로 따로 정의한 새로운 좌표값들을 INTERPOLATE 함수는 우리가 원하는 방식으로 인식하지 못하기 때문입니다. INTERPOLATE 함수는 데이터 배열의 격자 크기에만 충실하게 여전히 0~9, 0~9로 인식을 합니다. 그렇기 때문에 우리가 생각하는 경위도 좌표 [133.0, 37.6]는 data 배열이 점유하는 범위로부터 너무나 멀리 떨어진 지점으로 인식될 수 밖에 없습니다. 그래서 0.912와 같은 전혀 엉뚱한 값이 산출된 것입니다. 결국은 INTERPOLATE 함수에 투입될 좌표값들은 새로운 좌표 범위에 맞게 재조정된 값들이 되어야 한다는 얘기입니다. 따라서 이를 고려한 보정 작업이 필요하게 되며 이 작업이 약간 귀찮게 느껴질 수 있습니다. 여기서는 다음과 같이 해주면 됩니다.
xp_mod = (xp-120)/20*10
yp_mod = (yp-30)/20*10
PRINT, xp_mod, yp_mod
여기서는 xp의 값에 대하여 하한값인 120을 뺀 다음 경도 범위 20으로 나누고 격자 갯수 10을 곱하였습니다. 그리고 yp에 대해서도 유사한 요령으로 계산하면 됩니다. 경도 범위의 경우 값 자체로만 보면 120~138이지만 격자 크기가 2이므로 점유 범위는 120~140이라고볼 수 있기 때문에 이렇게 한 것입니다. 위도 범위도 값 자체로만 보면 30~48이지만 같은 요령으로 생각하면 30~50으로 볼 수 있습니다. 이와 같은 방식으로 보정된 좌표값들인 xp_mod, yp_mod의 값들을 출력해보면 다음과 같습니다.
6.50000 3.80000
이렇게 보정된 좌표값들을 다음과 같이 INTERPOLATE 함수에 투입하면 그 결과값은 66.6096이라는 정상적인 값으로 산출됩니다.
result = INTERPOLATE(data, xp_mod, yp_mod)
PRINT, result
그래서 격자 좌표의 범위를 따로 고려해야 할 경우에는 이러한 점을 유의해야 합니다. 그리고 여기서도 내삽할 지점들이 다수일 경우에는 앞서와 마찬가지로 X 및 Y 방향 좌표값들을 각각 배열로 주면 됩니다. 예를 들면 다음과 같습니다.
xp = [133.0, 126.8, 131.3]
yp = [37.6, 35.7, 42.3]
물론 나머지 다른 과정들은 동일합니다. 결과로 출력되는 내삽값들은 다음과 같습니다.
66.6096 45.8859 81.3194
그리고 지점들의 분포는 다음과 같습니다.
이상 오늘은 INTERPOLATE 함수를 사용하여 규칙 격자 분포를 하는 2차원 데이터를 기반으로 내삽을 하는 예제를 살펴보았습니다.
'IDL > Math' 카테고리의 다른 글
IDL로 Monte Carlo 방법을 테스트해봅시다 (0) | 2019.03.18 |
---|---|
사분위수(Quartile) 값의 계산 (0) | 2019.02.25 |
GAUSS_PDF 및 GAUSS_CVF 함수의 이해 (0) | 2018.08.21 |
비선형(Non-linear) 함수의 근사(Fitting) (Part 2) (0) | 2018.08.10 |
비선형(Non-linear) 함수의 근사(Fitting) (Part 1) (0) | 2018.08.09 |