IDL/New Graphics

플롯(Plot) 상에 축과 데이터 추가하기 [1]

이상우_idl 2024. 10. 16. 15:23
728x90
반응형

우리가 플롯(Plot) 형태의 그림을 표출할 경우에는 기본적으로 X 및 Y 데이터가 주어진 상태에서 X축 및 Y축으로 구성되는 공간 내에서 데이터 포인트들이 표시되도록 하는 방식이 일반적입니다. 그런데 경우에 따라서는 추가적인 데이터를 중첩하면서 X축 또는 Y축을 추가로 표시하고 싶은 경우가 종종 있습니다. 이러한 작업은 NG 체계를 기준으로 본다면, 먼저 주어진 데이터에 해당되는 플롯을 PLOT 함수로 표출한 상태에서 AXIS 함수를 사용하여 새로운 축을 추가하고 새로운 데이터에 해당되는 플롯도 추가하는 방식이 됩니다. 예를 하나 들어본다면 아마 다음과 같은 형태의 그래픽 표출이 될 것입니다.

 

그래서 오늘은 NG 체계에서 PLOT 함수 및 AXIS 함수를 사용하여 이러한 작업을 수행하는 방법에 관하여 소개를 해보고자 합니다. 먼저 예제로 사용할 데이터를 다음과 같이 생성해봅시다.

 

x = FINDGEN(101)
y1 = SQRT(x)
y2 = (x/10)^2+100

 

여기서는 동일한 x 배열로 생성되는 두 종류의 Y 데이터 배열인 y1, y2를 생성하였습니다. 여기서 생성된 x, y1, y2는 모두 101개의 값들로 구성된 1차원 배열이 됩니다. 그러면 이 상태에서 먼저 x, y1에 대한 기본적인 플롯부터 표출해봅시다. 그 과정은 다음과 같이 처리합니다.

 

win = WINDOW(DIMENSIONS=[600, 500], /NO_TOOLBAR)

p = PLOT(x, y1, COLOR='green', YTITLE='Y1', $
  FONT_SIZE=11, MARGIN=0.1, /CURRENT)

 

여기까지는 그냥 x, y1에 대한 플롯을 표출하는 지극히 평범한 과정입니다. 표출 결과는 다음과 같습니다.

 

그러면 여기서 x, y2에 대한 플롯을 중첩하여 표출해봅시다. 이미 표출되어있는 플롯 상에 또 다른 데이터를 중첩하는 방법이라면 흔히 PLOT 함수와 /OVERPLOT 키워드를 사용하는 방식을 떠올리는 것이 일반적입니다. 예를 들면 다음과 같은 내용을 추가로 실행하는 방식입니다.

 

po = PLOT(x, y2, COLOR='tomato', /OVERPLOT)

 

하지만 실제로 위와 같은 내용을 추가로 실행해보면 표출 결과는 다음과 같을 것입니다.

 

물론 새로운 데이터가 중첩되어 표출이 된 것 자체는 맞지만 앞서 맨 처음에 제시되었던 예제 그림과는 많이 다릅니다. 그럴 수 밖에 없는 것이 y1의 경우 값 범위가 0~10이지만 y2의 경우는 100~200입니다. 즉 두 데이터의 값 범위가 서로 매우 다른 상태에서 두 데이터의 범위를 모두 반영하느라 그림이 위와 같이 되어버린 것입니다. 그렇다면 앞서 맨 처음에 제시되었던 것과 같은 모습으로 표출을 하려면 어떻게 해야 할까요? 기본적으로는 AXIS 함수를 사용하여 y2 데이터에 맞는 Y축을 별도로 표시하는 것이 필요합니다. 다만 여기서는 이미 표출되어있는 플롯 상에서 우측의 Y축을 새로 대체할 것이므로 먼저 기존 플롯의 우측 Y축을 보이지 않도록 처리하는 것이 바람직합니다. 이러한 작업을 위하여 다음과 같은 내용을 추가하면 됩니다. 다만 우리가 바로 위에서 실행했던 po = PLOT(~~~) 내용은 삭제해야 합니다.

 

axes = p.AXES
axes[3].HIDE = 1

 

이 내용은 이미 표출된 플롯 개체인 p를 구성하는 모든 축 개체들 중 우측의 Y축에 해당되는 축 개체인 axes[3]에 대하여 HIDE 속성을 1로 설정함으로써 눈에 보이지 않도록 처리하는 과정입니다. 위의 내용까지 실행된 결과는 다음 그림과 같습니다.

 

새로운 축을 추가하려면 먼저 위와 같이 그 자리를 비워두는(?) 것을 권장합니다. 왜냐하면 새로운 축은 눈금 체계가 기존 축과 다를 수 있기 때문에 이렇게 미리 자리를 비워두지 않으면 기존 축과 새로운 축이 겹쳐서 보일 수 있기 때문입니다. 이제는 새로운 Y축을 이 자리에 추가해야 하므로, 다음과 같이 AXIS 함수를 사용하여 이러한 작업을 진행합시다.

 

axo = AXIS('Y', LOCATION='right', AXIS_RANGE=[100, 200], $
    COLOR='tomato', TICKFONT_SIZE=11, TITLE='Y2')

 

여기서 AXIS 함수의 내용을 보면 먼저 'Y'라는 인수가 보이는데 바로 Y축을 추가하겠다는 의미입니다. 그리고 LOCATION 속성이 'right'이므로 새로운 Y축은 이미 표출되어 있는 플롯 상에서 우측에 위치하게 됩니다. 그리고 AXIS_RANGE 속성이 [100, 200]으로 명시되어 있는데 이것은 새로운 Y축이 y2 데이터의 범위 즉 100~200의 범위를 나타내도록 하는 것이 목적이기 때문에 축 자체도 그러한 범위가 되도록 설정한 것입니다. 또한 이러한 새로운 Y축에 해당되는 요소들은 전부 별도의 색상으로 처리하였습니다. 위의 내용을 추가하여 다시 실행해보면 그 결과는 다음 그림과 같을 것입니다.

 

그런데 이 그림을 보면 플롯 그림의 우측에 새로운 Y축이 표시된 것은 맞긴 하지만 결정적인 문제가 있습니다. 즉 새로 추가된 Y축도 그 범위가 여전히 0~10이라는 것입니다. 우리의 의도는 100~200이 되도록 하는 것이었는데 전혀 반영이 안되었습니다. 사실 여기서는 우리가 한가지를 더 고려해줘야 합니다. 바로 AXIS 함수에 COORD_TRANFORM이라는 속성을 추가로 사용하는 것이 반드시 필요합니다. 그러면 위의 AXIS 함수가 사용되었던 내용을 다음과 같이 수정해봅시다.

 

axo = AXIS('Y', LOCATION='right', AXIS_RANGE=[100, 200], $

  COORD_TRANSFORM=[100, 10], $
  COLOR='tomato', TICKFONT_SIZE=11, TITLE='Y2')

 

여기서 COORD_TRANSFORM 속성이 필요한 이유를 살펴볼 필요가 있습니다. 원래 AXIS 함수로 별도의 축을 표시하기 위해서는 기존에 XY 축을 갖는 그림이 이미 표출된 상태에서 그 그림 개체를 대상으로 구현되어야 합니다. 즉 아무 그림도 표출되지 않은 상태에서 AXIS 함수만 사용하여 축만 단독으로 표출할 수는 없다는 것입니다. 따라서 지금 소개하고 있는 예제에서도 AXIS 함수로 구현되는 새로운 Y축은 기존에 이미 PLOT 함수로 표출되어 있는 플롯 그림에 소속된 개체가 됩니다. 그러므로 새롭게 추가되는 Y축 역시 근본적으로는 기존에 이미 표출되어 있는 플롯의 X축 및 Y축의 데이터 좌표계를 일단 그대로 이어받습니다. 결국 새로운 Y축이 우리의 의도대로 100~200의 범위가 되도록 하려면 기존 플롯의 Y축 범위인 0~10을 기반으로 새로운 축 범위값으로 변환되도록 하는 것이 필요한데 그러한 역할을 바로 COORD_TRANSFORM 속성이 담당한다고 보면 됩니다. 이 속성에 투입되는 값은 두 개로 구성되는데 첫번째 값은 변환의 offset이고 두번째 값은 변환의 배율입니다. 따라서 위의 내용에서 COORD_TRANSFORM 속성에 부여된 [100, 10]의 의미는 기존 플롯의 Y축 범위인 0~10에 대하여 10배를 곱하고 100을 더해주면 새로운 Y축 범위인 100~200이 된다는 것입니다. 이러한 변경사항을 적용하여 다시 실행해보면 결과는 다음 그림과 같습니다.

 

그러면 일단 새로운 Y축은 우리의 의도대로 표시가 된 것 같습니다. 그 다음은 y2 데이터에 해당되는 플롯을 추가하는 것입니다. 이를 위하여 다음과 같은 내용을 추가해봅시다.

 

po = PLOT(x, y2, AXIS_STYLE=0, COLOR='tomato', MARGIN=0.1, /CURRENT)

 

위의 내용을 잘 보면 일단 PLOT 함수에 x, y2 데이터를 투입한 것은 당연히 필요한 것이므로 별로 특별할 것은 없습니다. 그런데 잘 보면 /OVERPLOT 키워드를 사용하지 않고 그 대신 /CURRENT 키워드를 사용하였음을 유의해야 합니다. 그리고 또 하나 주목할 것은 AXIS_STYLE 키워드의 값을 0으로 설정한 것인데요. 이렇게 하면 플롯을 표시할 때 X축, Y축은 전혀 표시하지 않고 그냥 데이터에 대한 플롯 선만 표시가 됩니다. 결국 위의 내용은 x, y2에 대한 플롯을 별도로 그린 것입니다. 다만 축들은 전혀 표시하지 않고 여백은 이전의 플롯과 동일하게 설정함으로써 마치 x, y2 데이터에 대한 플롯 선만 중첩하는 것과 동일한 효과를 얻게 됩니다.

 

여기서 잠깐 이해를 돕기 위하여 기존의 플롯은 무시하고 바로 위의 내용만 실행하여 표출된 그림을 보면 실제로 다음과 같습니다.

 

결국은 앞서 표출했던 플롯과 바로 위의 플롯을 합쳐서 표시하면 우리가 원하는 그림을 얻게 됩니다. 따라서 이전의 내용들을 모두 다시 살리고 다시 실행해보면 그 결과는 다음과 같을 것입니다.

 

여기서 조금만 더 나아가본다면 기존 플롯의 좌측 Y축의 색상도 데이터와 맞춰주면 좋을 것 같습니다. 이러한 처리는 다음과 같이 해주면 됩니다.

 

axes[1].COLOR = 'green'

 

여기서는 기존 플롯인 p를 구성하는 축 개체들 중 좌측 Y축에 해당되는 axes[1]에 대하여 COLOR 속성을 변경한 것입니다. 이렇게 하면 결과는 다음 그림과 같습니다.

 

이 그림이 바로 서두에서 가장 먼저 제시되었던 것과 같은 그림입니다. 그리고 방금 PLOT 함수를 사용했던 내용을 보면 /CURRENT 키워드를 사용하는 방식이었는데요. 그 대신 /OVERPLOT 키워드를 사용하는 방식으로 처리하는 것도 가능합니다. 다만 그렇게 할 경우에는 바로 위의 PLOT 함수가 사용된 내용이 다음과 같이 변경되어야 합니다.

 

po = PLOT(x, (y2-100)/10., COLOR='tomato', /OVERPLOT)

 

여기서 신경써야 할 부분은 바로 투입된 Y 인수인데, 그냥 y2를 사용하는 것이 아니고 위와 같이 (y2-100)/10으로 명시해야 합니다. 이것은 앞서 AXIS 함수에서 사용했던 COORD_TRANSFORM 속성에 명시된 [100, 10]이라는 값들 즉 offset 및 배율에 해당되는 값들을 y2에 적용해야 현재의 플롯 공간 내에 올바르게 중첩이 되기 때문입니다. 이런 부분까지 신경써야 한다는 것이 다소 귀찮을 수도 있습니다. 그런 측면에서 보면 바로 앞서 소개했던 PLOT 함수와 /CURRENT 키워드를 사용하는 방식이 더 나을 수도 있는데, 결국 선택은 유저의 몫입니다. 어쨌든 플롯을 표출할 때 서로 다른 성격의 데이터들을 한 공간 내에 중첩하기 위해서는 X축 또는 Y축을 별도로 추가하는 것이 필요할 수 있는데, 이를 위하여 AXIS 함수를 사용할 때에는 위와 같은 내용을 유의하면 됩니다.

 

그리고 여기서는 서로 다른 두 종류의 데이터를 중첩하는 경우를 살펴보았지만 둘 이상의 데이터를 위와 같은 요령으로 중첩하는 것도 가능합니다. 이런 경우에도 AXIS 함수를 사용해야 한다는 것은 앞서 소개된 내용과 다르지 않지만, 조금 더 신경을 써줘야 할 부분들도 있습니다. 이러한 경우에 대해서는 다음 회차에서 이어서 소개해보기로 하겠습니다.

 

 

이 글이 도움이 되었다면 게시물에 대하여 공감 버튼(하트 모양) 클릭 및 블로그 구독도 해주시면 더 큰 힘이 됩니다. 감사합니다.

반응형