오늘은 모처럼 그래픽 관련 내용을 다뤄보고자 합니다. 오늘 다뤄볼 내용은 2차원 공간상에 존재하는 규칙 격자점들의 위치를 표시하는데 있어서 NG 체계의 SCATTERPLOT 함수를 이용하는 방법입니다. 결론부터 보여드린다면 다음 그림과 같은 결과를 얻는 방법을 소개하고자 합니다.
보시는대로 2차원 공간상에서 규칙적인 분포를 하는 격자점들이 있을 때 각 위치마다 특정한 심볼을 표시하는 작업입니다. 그런데 이것이 그림만 보면 참 단순해 보이는 작업일 수도 있는데, 막상 어떤 식으로 작업을 해야 이런 표출이 가능할지 생각해보면 의외로 막막할 수도 있는 문제이기도 합니다. 물론 이 작업은 어떤 그래픽 체계에서 어떤 그래픽 기능을 사용하여 구현할 것이냐에 따라 몇몇 종류의 해결 방법들을 생각해볼 수 있습니다. 위의 그림은 IDL의 NG 체계에서 지원되는 SCATTERPLOT 함수를 사용하여 얻은 것입니다. 따라서 이 방법을 기준으로 설명을 해보겠습니다.
그러면 먼저 위 그림을 얻기 위하여 사용된 예제 데이터부터 보겠습니다. 여기서는 5x4의 2차원 격자 구조를 가정하였습니다. 만약 이런격자 구조를 갖는 2차원 데이터를 다루는 경우라면, 예를 들어 다음과 같은 형태의 예제 2차원 데이터를 생각해볼 수 있습니다.
data = FINDGEN(5, 4)
그런데 2차원 데이터를 표출하는 작업일 경우에는 IMAGE, CONTOUR, SURFACE 등의 그래픽 기능들을 주로 사용합니다. 하지만 이러한 2차원 데이터의 격자점들의 위치를 표시하는 것은 또 다른 종류의 작업이고, 이러한 작업에 있어서는 SCATTERPLOT과 같은 기능을 사용하는 것이 효율적입니다. 격자점들의 위치는 위 그림에서 보는 것처럼 X축 방향으로는 1, 2, 3, 4, 5이고 Y축 방향으로는 1, 2, 3, 4인것으로 가정합시다. 이러한 격자점 위치 좌표값들을 다음과 같이 X, Y 방향별 배열로 만들어 둡시다.
px = [1, 2, 3, 4, 5]
py = [1, 2, 3, 4]
그 다음 단계는 어떤 작업이 되어야 할까요? 얼핏 생각해보면 이 시점에서 바로 SCATTERPLOT 함수를 바로 사용하여 결과를 얻을 수 있으면 좋겠다는 생각이 드는 것도 사실입니다. 하지만 안타깝게도 SCATTERPLOT 함수의 사용까지 가려면 적어도 1~2 단계 정도를 더 거쳐야 합니다. 그 이유를 이해하려면 SCATTERPLOT 함수의 사용 문법을 봐야 하는데, IDL 도움말에 의하면 다음과 같습니다.
graphic = SCATTERPLOT(X, Y [, Keywords=value] [, Properties=value])
X , Y
Vectors of equal length representing the abscissa (X) and ordinate (Y) values to be plotted.
또한 여기서 필요로 하는 두 인수 X, Y 각각은 1차원 배열이어야 합니다. 즉 X는 표시하고자 하는 모든 격자점들의 X좌표값들로만 구성된 배열이어야 하고, Y는 표시하고자 하는 모든 격자점들의 Y좌표값들로만 구성된 배열이어야 합니다. 지금 우리의 예제에서 격자점들의 총 갯수가 5X4=20개이므로, SCATTERPLOT 함수에 투입될 X, Y 두 인수는 각각 20개씩의 값들로 구성된 배열이 되어야 한단 얘기입니다. 이 과정을 위해서는 약간의 배열 연산 과정이 필요한데, 일단 그 내용은 다음과 같습니다.
crdx = px#[1, 1, 1, 1]
crdy = py##[1, 1, 1, 1, 1]
xx = REFORM(crdx, N_ELEMENTS(crdx))
yy = REFORM(crdy, N_ELEMENTS(crdy))
물론 이 내용을 이해하기 위해서는 IDL에서 행렬연산자로 사용되는 #과 ##를 알아야 하고, REFORM이라는 배열 처리용 함수를 알아야 합니다. 그런데 그 내용에 대해서는 조금 있다가 보기로 하고, 일단 먼저 표출 과정부터 봅시다. 그 내용은 다음과 같습니다.
win = WINDOW(DIMENSIONS=[600, 500], /NO_TOOLBAR)
pl = SCATTERPLOT(xx, yy, XRANGE=[0, 6], YRANGE=[0, 5], $
SYMBOL='circle', /SYM_FILLED, SYM_COLOR='crimson', SYM_SIZE=2, /CURRENT)
여기서는 SCATTERPLOT 함수를 활용하여 각 격자 위치에 대하여 붉은색으로 채워진 원형 심볼을 표시하고 있습니다. 물론 이 내용에서는 앞서 조금 요상한(?) 과정을 통하여 얻은 xx, yy를 SCATTERPLOT 함수에서 인수로 사용하였습니다. 어쨌든 표출 부분은 이렇게 비교적 간단합니다. 그래서 여기까지만 보셔도 되긴 합니다. 다만 xx, yy를 얻는 과정에 대해서도 궁금하실 분들을 위하여 설명을 조금만 더 덧붙이겠습니다.
이 내용에 대한 이해를 돕기 위하여 먼저 다음과 같이 crdx와 crdy의 구조 및 구성원소들을 출력하도록 해봅시다.
HELP, crdx & PRINT, crdx
HELP, crdy & PRINT, crdy
그러면 다음과 같은 내용이 출력될 것입니다.
CRDX LONG = Array[5, 4]
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
CRDY LONG = Array[5, 4]
1 1 1 1 1
2 2 2 2 2
3 3 3 3 3
4 4 4 4 4
이 내용을 보면 crdx는 모든 격자점들 각각에 대한 X좌표값들로만 구성되어 있는 2차원 배열이고 crdy는 모든 격자점들 각각에 대한 Y좌표값들로만 구성되어 있는 2차원 배열임을 알 수 있습니다. 이 crdx, crdy를 생성하기 위하여 행렬연산자인 #과 ##이 사용되었는데, 이 방법에 관해서는 제가 예전에 올렸던 관련 게시물의 내용을 참조하시기 바랍니다.
그 다음으로 xx, yy의 구조 및 구성원소들을 확인하기 위하여 다음과 같은 명령도 추가해 봅시다.
HELP, xx & PRINT, xx
HELP, yy & PRINT, yy
그러면 다음과 같은 내용이 출력될 것입니다.
XX LONG = Array[20]
1 2 3 4 5 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5
YY LONG = Array[20]
1 1 1 1 1 2 2 2 2 2 3 3 3 3 3 4 4 4 4 4
이 내용을 보면 xx는 원래 2차원이었던 crdx를 1차원 배열로 변환한 것이고, yy는 원래 2차원이었던 crdy를 1차원 배열로 변환한 것임을 알 수 있습니다. 이렇게 굳이 1차원 배열로 변환한 것은 SCATTERPLOT 함수의 두 인수 모두 1차원 배열이어야 하기 때문입니다. 그리고 이 과정에서 사용된 REFORM 함수는 어떤 배열에 대하여 총 원소갯수는 유지하되 차원만 변경하는 역할을 합니다. REFORM에 대해서도 역시 제가 예전에 올렸던 관련 게시물이 있으므로 이 내용도 참조해보시면 좋습니다.
오늘은 이 정도로 소개를 마쳐봅니다. 솔직히 굉장히 단순한 표출처럼 보일 수도 있겠지만, 이러한 표출을 위해서 의외로 다소 복잡한 배열 처리 과정이 필요할 수도 있는 하나의 예제로서 생각해주시면 좋을 것 같습니다.
'IDL > New Graphics' 카테고리의 다른 글
서피스(Surface) 그림의 시선방향 설정 (0) | 2018.11.02 |
---|---|
NG 체계에서도 POLAR_CONTOUR를? (0) | 2018.09.03 |
2차원 데이터 표출시 축(axis)에 대한 로그 스케일(log scale) 적용 방법 (0) | 2018.03.19 |
Windows 10용 IDL에서 NG 체계 그림 저장 문제 및 해결 방법 (0) | 2018.02.12 |
VECTOR 함수를 이용하여 벡터 필드 표출하기 [2] (0) | 2017.12.07 |