IDL/배열 생성 및 처리

ARRAY_INDICES 함수의 필요성

이상우_idl 2024. 2. 14. 15:26
728x90
반응형

오늘 살펴보고자 하는 ARRAY_INDICES 함수에 관해서는 예전에 몇몇 게시물들을 통하여 간접적으로 언급했던 적이 있긴 합니다만, 오늘은 이 함수 자체에 좀 더 촛점을 맞춰서 다뤄보고자 합니다. 이 함수는 특히 다차원(2차원, 3차원 등) 배열을 취급할 때 그 필요성이 커지는데요. 예제와 함께 그 쓰임새를 살펴봅시다. 먼저 다음과 같이 4x3의 구조를 갖는 2차원 배열을 하나 가정해보겠습니다.

 

arr = INTARR(4, 3)
arr[1, 2] = 1
arr[2, 1] = 2
arr[3, 1] = 1
PRINT, arr

 

여기서 정의된 배열 arr의 값들이 출력된 모습은 다음과 같습니다.

 

       0       0       0       0
       0       0       2       1
       0       1       0       0

 

이 배열 내에서 최대값은 2일 것입니다. 그리고 최대값인 2가 배열 arr 내에서 어느 위치에 있는가를 명시적으로 알아내려면 다음과 같이 WHERE 함수를 사용하면 됩니다.

 

ww = WHERE(arr EQ 2, count)
PRINT, ww

 

여기서 ww는 배열 arr 내에서 값이 2인 위치에 해당됩니다. 출력된 내용을 보면 다음과 같습니다.

 

           6

 

하지만 이 값은 좀 생뚱맞게 느껴질 수가 있습니다. 왜냐하면 arr은 2차원 배열이므로 2차원 배열 내에서의 위치라면 당연히 (x, y)와 같은 좌표가 되어야 한다고 생각하는 것이 자연스럽기 때문입니다. 하지만 IDL에서는 배열의 차원이 얼마가 되든간에 고유 위치의 값은 이와 같이 단일값으로 인식되는 것이 기본입니다. 즉 어떤 차원의 배열이든간에 배열 내 인덱스를 IDL 내부적으로는 이렇게 인식한다는 정도로 이해하시면 됩니다. 사실 다른 프로그래밍 언어들의 경우도 세부적인 방식의 차이는 있을 수 있지만 내부적으로는 비슷한 맥락으로 배열 인덱스를 인식하는 경우가 꽤 있는 것으로 알고 있습니다. 이것은 해당 프로그래밍 언어가 배열 인덱스를 인식하는 고유의 방식이 이렇다 정도로 생각하시면 됩니다. 이제 여기서 그 위치에 해당되는 인덱스 값이 6이 되는 근거를 도식적으로 보면 다음과 같습니다.

 

 

이 내용을 보면 배열 arr 내에서 값이 2인 위치에 대한 고유 인덱스가 6이 됨을 알 수 있습니다. 따라서 IDL은 내부적으로는 배열 내 위치를 이러한 방식으로 인식한다고 보면 됩니다. 물론 배열의 차원이 더 높아지면 그 방식도 더 복잡해지겠지만 유저 입장에서는 그러한 부분에 대해서까지 깊게 파고들 필요는 없을 것 같습니다. 중요한 것은 이러한 고유한 위치 인덱스를 우리가 알아보기 쉬운 좌표로 환산하는 것입니다. 이를 위해서 사용해야 하는 함수가 바로 ARRAY_INDICES 함수입니다. 그러면 이 함수를 사용해봅시다. 과정은 다음과 같습니다.

 

r = ARRAY_INDICES(arr, ww)
HELP, r
PRINT, r

 

이와 같이 원래 배열인 arr과 고유 위치 인덱스 정보인 ww를 ARRAY_INDICES 함수에 인수로 투입하면 됩니다. HELP 및 PRINT에 의하여 출력된 내용을 보면 다음과 같습니다.

 

R               LONG      = Array[2]
           2           1

 

이와 같이 두 개의 값들로 구성되는데 각각 X 방향 및 Y 방향의 인덱스인 2와 1이 됩니다. 즉 배열 arr 내에서 값이 2인 위치 좌표가 (2, 1)이 된다는 의미입니다. 이렇게 해야 우리가 쉽게 인지할 수 있는 위치 좌표의 형태로 결과를 얻을 수 있습니다. 그러면 이번에는 동일한 배열 arr에 대하여 다음과 같이 다른 조건을 내걸어봅시다.

 

ww = WHERE(arr GE 1, count)
PRINT, count
PRINT, ww

 

여기서는 배열 arr 내에서 1보다 크거나 같은 값들의 위치를 찾아내도록 하였습니다. 우선 count 변수에는 제시된 조건을 만족하는 경우의 수가 저장됩니다. 이 변수 count를 비롯하여 조건을 만족하는 값들의 위치 정보인 ww까지 모두 출력된 내용을 보면 다음과 같습니다.

 

           3
           6           7           9

 

즉 경우의 수는 3이고 각각의 고유 위치 인덱스는 6, 7, 9라는 의미입니다. 그러면 이 결과를 2차원적인 위치 좌표 값들로 환산해봅시다. 이를 위하여 동일한 방식으로 ARRAY_INDICE 함수를 활용해보면 다음과 같습니다.

 

r = ARRAY_INDICES(arr, ww)
HELP, r
PRINT, r

 

그리고 출력된 내용을 보면 다음과 같습니다.

 

R               LONG      = Array[2, 3]
           2           1
           3           1
           1           2

 

일단 이 내용을 보면 해당 값들의 위치 좌표는 (2, 1), (3, 1), (1, 2)임을 알 수 있습니다. 그런데 결과인 r 자체는 2x3의 구조를 갖는 2차원 배열로 얻어졌습니다. 만약 해당 값들의 X 좌표값들만 따로 그리고 Y 좌표값들만 따로 모아서 각각에 대한 배열을 얻고자 한다면 다음과 같은 과정이 추가적으로 필요합니다.

 

x = REFORM(r[0, *])
y = REFORM(r[1, *])
HELP, x, y
PRINT, x
PRINT, y

 

이와 같이 결과 배열인 r에서 X 방향 좌표값들 및 Y 방향 좌표값들을 각각 따로 추출하면 됩니다. HELP 및 PRINT에 의하여 출력된 내용을 보면 다음과 같습니다.

 

X               LONG      = Array[3]
Y               LONG      = Array[3]
           2           3           1
           1           1           2

 

이 내용을 보면 우리의 의도대로 결과를 얻었음을 확인할 수 있습니다. 이러한 방식으로 얻은 결과는 후속 작업에서 요긴하게 사용될 수 있을 것입니다. 결국 우리가 IDL에서 배열 데이터에 대하여 WHERE 함수를 사용하여 특정 조건에 대한 탐색 결과를 얻었을 때, 이 결과를 쉽게 해석하여 후속 작업에서 응용하고자 할 경우 ARRAY_INDICES 함수가 상당히 중요한 역할을 할 수 있음을 참고해두는 것이 좋을 것입니다. 그러면 이번에는 2차원 이미지에 대하여 WHERE 함수를 사용하여 결과를 얻고 이 결과에 대하여 ARRAY_INDICES 함수를 적절히 활용하는 예제를 살펴봅시다. 일단 예제로 사용될 2차원 이미지 데이터는 다음과 같이 정의합니다.

 

data = HANNING(600, 600)*100
add = FLTARR(600, 600)
add[300, 300] = HANNING(300, 300)*50
data = data+add+RANDOMU(-1, 600, 600)*10
PRINT, MIN(data), MAX(data)
win = WINDOW(DIMENSIONS=[600, 600], /NO_TOOLBAR)
i = IMAGE(data, RGB_TABLE=0, MARGIN=0, /CURRENT)

 

여기서 생성된 2차원 배열 data는 대략 0~110 정도의 값 범위를 갖습니다. 이미지의 형태로 표출된 이 데이터의 모습은 다음 그림과 같습니다.

 

 

그러면 여기서 다음과 같이 WHERE 함수를 사용하여 특정한 조건을 만족하는 값들을 탐색해봅시다.

 

ww = WHERE(data GE 60 AND data LE 65 OR data GE 95 AND data LE 100, count)
PRINT, count

 

여기서는 조건을 다소 복잡하게 걸어봤는데, 값의 범위가 60~65 또는 95~100이라는 조건을 만족하는 값들을 전부 찾아보도록 한 것입니다. 출력된 결과를 보면 다음과 같습니다.

 

       16095

 

즉 조건을 만족하는 값들의 갯수가 총 16095개라는 의미입니다. 그러면 ARRAY_INDICES 함수를 사용하여 X 방향 및 Y 방향 좌표값들을 각각 모아봅시다.

 

ri = ARRAY_INDICES(data, ww)
HELP, ri
xi = REFORM(ri[0, *])
yi = REFORM(ri[1, *])

 

이렇게 얻어진 xi 및 yi를 어떻게 활용해볼까요? 한가지 예를 든다면 SCATTERPLOT 함수를 사용하여 해당 값들의 위치를 모두 표시해볼 수 있습니다. 즉 다음과 같은 과정을 추가하는 것입니다.

 

sc = SCATTERPLOT(xi, yi, SYMBOL='circle', SYM_COLOR='purple', $
  /SYM_FILLED, SYM_SIZE=0.1, /OVERPLOT)

 

이 과정까지 모두 실행된 결과는 다음 그림과 같습니다.

 

 

그리고 여기서 조금만 더 응용을 해보면, 두 종류의 조건을 가정하여 각 조건에 맞는 값들을 선별하고 각각 다른 색상으로 나타내는 것도 충분히 가능합니다.

 

ww = WHERE(data GE 60 AND data LE 65, count)
ri = ARRAY_INDICES(data, ww)
xi1 = REFORM(ri[0, *])
yi1 = REFORM(ri[1, *])
sc1 = SCATTERPLOT(xi1, yi1, SYMBOL='circle', SYM_COLOR='magenta', $
  /SYM_FILLED, SYM_SIZE=0.1, /OVERPLOT)

ww = WHERE(data GE 95 AND data LE 100, count)
ri = ARRAY_INDICES(data, ww)
xi2 = REFORM(ri[0, *])
yi2 = REFORM(ri[1, *])
sc2 = SCATTERPLOT(xi2, yi2, SYMBOL='circle', SYM_COLOR='royal blue', $
  /SYM_FILLED, SYM_SIZE=0.1, /OVERPLOT)

 

이와 같이 처리하면 다음과 같은 결과를 얻을 수 있습니다.

 

 

따라서 앞서 이미 언급했듯이 ARRAY_INDICES 함수는 특히 다차원 배열에 대하여 WHERE 함수를 적용한 탐색 결과를 우리가 알아보기 쉽게 직관적으로 변환하고 후속 작업에 활용할 수 있도록 하는데 있어서 매우 유용하게 사용될 수 있다는 점을 항상 염두에 두시면 좋을 것 같습니다.

반응형