IDL/New Graphics

IDL에서 표(Table) 그리기(?)

이상우_idl 2022. 12. 27. 13:34
728x90
반응형

오늘은 조금 특이한 주제를 갖고 얘기를 해보고자 합니다. 글 제목 그대로 IDL에서 표(Table)을 그려보고자 하는데요. 사실 표(Table)라는 것이 우리가 파워포인트나 워드 등과 같은 일반적인 사무용 앱들에서는 당연히 편리하게 그릴 수 있습니다. 그러나 하나의 프로그래밍 언어인 IDL의 경우 비교적 다양한 그래픽 표출 기능들이 포함되어 있음에도 불구하고 표를 그릴 수 있는 기능은 포함되어 있지 않습니다. 따라서 제가 오늘 소개하려는 내용은 그나마 있는 기능들을 나름 활용해서 되도록이면 표와 비스무리한 표출을 시도해보려는 의도입니다. 그렇기 때문에 우리가 다른 앱들에서 편리하게 표를 그렸던 것에 비해서는 다소 번거로운 코딩이 들어갈 수 밖에 없습니다. 다만 우리가 IDL에서 얻은 결과가 2차원적인 데이터가 될 경우에는 이러한 표 형식의 표출이 필요할 수도 있습니다. 그런 경우에는 나름 나쁘지않은 해결책이 될 수 있을 것 같기 때문에, 제 경험을 토대로 하여 소개를 해보겠습니다.

 

일단 목표는 8x6의 셀 구조를 갖는 표를 IDL로 구현해보고자 하는 것입니다. 먼저 그래픽창을 띄우고 그 안에 간단한 플롯을 하나 표출하는 것으로 시작합니다. 그 과정은 다음과 같습니다.

 

y = INDGEN(11)
win = WINDOW(DIMENSIONS=[800, 600], /NO_TOOLBAR)
p = PLOT(y, XRANGE=[0, 8], YRANGE=[0, 6], $
  MARGIN=0.1, /CURRENT)

 

여기서는 먼저 임의의 데이터 y를 정의하고 PLOT 함수를 사용하여 간단한 플롯을 표출하였습니다. 사실 y는 그냥 플롯을 표출하기 위한 목적으로 정의한 것일 뿐 더 이상의 의미는 없기 때문에 나중에는 보이지않도록 처리할 예정입니다. 그리고 X축의 범위는 0~8, Y축의 범위는 0~6으로 설정하였습니다. 일단 이 과정에 의한 표출 결과는 다음 그림과 같습니다.

 

 

당연히 우리의 목표와는 전혀 동떨어진 모습이지만 이제부터 다듬어나갈 것입니다. 이제 8x6의 셀 구조를 갖는 표의 형태를 갖추도록 하기 위하여 PLOT 함수의 내용을 다음과 같이 수정해봅시다.

 

p = PLOT(y, XRANGE=[0, 8], YRANGE=[0, 6], $
  XTICKINTERVAL=1, YTICKINTERVAL=1, $
  XTICKLEN=1, YTICKLEN=1, XMINOR=0, YMINOR=0, $
  MARGIN=0.1, /CURRENT)

 

여기서는 X 및 Y 축에 대한 몇가지 세부 속성들을 조정하였습니다. 먼저 TICKINTERVAL 속성으로 각 축의 눈금 간격을 1로 설정하였고, TICKLEN 속성을 1로 설정하여 각 축의 눈금의 길이가 1이 되도록 하였습니다. 그리고 MINOR 속성을 0으로 설정하여 마이너 눈금들이 보이지 않도록 하였습니다. 이러한 수정사항들이 반영된 모습은 다음 그림과 같습니다.

 

 

물론 아직은 해야 할 일이 더 남아있지만, 이 모습만 봐도 우리의 목표에 조금씩 다가가고 있음을 느낄 수 있습니다. 이제 좀 더 표에 가까운 모습을 띄기 위해서는, 눈금 숫자들도 사실 더 보일 필요가 없을 것이고 데이터 라인도 보이지 않도록 해야 할 것 같습니다. 이러한 처리를 위하여 PLOT 함수의 내용을 다음과 같이 수정합니다.

 

p = PLOT(y, XRANGE=[0, 8], YRANGE=[0, 6], $
  XTICKINTERVAL=1, YTICKINTERVAL=1, $
  XTICKLEN=1, YTICKLEN=1, XMINOR=0, YMINOR=0, $
  XSHOWTEXT=0, YSHOWTEXT=0, /NODATA, $
  MARGIN=0.1, /CURRENT)

 

여기서는 SHOWTEXT 속성을 0으로 설정하여 각 축의 눈금 숫자들이 안보이도록 하고, /NODATA 키워드를 사용하여 데이터 라인의 모습이 보이지 않도록 처리하였습니다. 이러한 수정사항들이 반영된 모습은 다음 그림과 같습니다.

 

 

그러면 원래 우리가 의도했던 8x6의 셀 구조를 갖는 표의 모습이 일단 구현된 것 같습니다. 그러면 이제는 각 셀 안에 뭔가 내용이 표시되도록 하는 것이 필요할 것입니다. 그래서 뭔가 가상의 데이터를 생성하여 그 값들이 각 셀 안에 표시되도록 해보기 위하여, 다음과 같이 0부터 34까지 35개의 정수값들로 구성되는 data라는 배열을 7x5의 2차원 배열로서 생성해봅시다.

 

data = INDGEN(7, 5)

 

그리고 이 data 배열의 값들이 각 셀에 문자로 표시되도록 하기 위하여 다음과 같이 TEXT 함수에 의한 문자 표시 작업이 반복형 구문에 의하여 실행되도록 합니다.

 

FOR j = 0, 4 DO BEGIN
  FOR i = 0, 6 DO BEGIN
    t = TEXT(i, j, STRING(data[i, j], FORMAT='(I0)'), /DATA)
  ENDFOR
ENDFOR

 

그 결과는 다음 그림과 같습니다.

 

 

일단 표를 구성하는 각 셀 안에 숫자가 표시되도록 하는 것은 성공한 것 같습니다. 하지만 아직은 추가 작업이 더 필요합니다. 먼저 숫자들이 표시된 순서를 봅시다. 일단 우리의 의도는 숫자들이 다음과 같은 순서로 표시되는 것입니다.

 

0 1 2 3 4 5 6

7 8 9 10 11 12 13

..................

 

그런데 위 그림을 보면 숫자들의 표시 순서에 있어서 위아래가 반대임을 알 수 있습니다. 그리고 나중을 위하여 맨 왼쪽의 컬럼(column)은 비워두는 것이 좋을 것 같습니다. 따라서 이러한 방식으로 문자 표시의 위치 및 순서를 바꾸기 위하여 반복형 구문의 내용을 다음과 같이 수정해봅시다.

 

FOR j = 0, 4 DO BEGIN
  FOR i = 0, 6 DO BEGIN
    t = TEXT(i+1, 6-j-1, STRING(data[i, j], FORMAT='(I0)'), /DATA)
  ENDFOR
ENDFOR

 

그러면 결과는 다음 그림과 같습니다.

 

 

이 그림을 보면 숫자값들이 표시되는 순서는 우리의 의도와 맞는 것 같습니다. 그 다음 고려사항은 각 셀 내에서 숫자가 표시되는 위치인데요. 셀의 가운데에 표시되도록 하는 것이 좋을 것입니다. 따라서 TEXT 함수의 내용을 다음과 같이 수정해봅시다.

 

FOR j = 0, 4 DO BEGIN
  FOR i = 0, 6 DO BEGIN
    t = TEXT(i+1.5, 6-j-1.5, STRING(data[i, j], FORMAT='(I0)'), $
      ALIGNMENT=0.5, VERTICAL_ALIGNMENT=0.5, FONT_SIZE=11, /DATA)
  ENDFOR
ENDFOR

 

여기서는 ALIGNMENT, VERTICAL_ALIGNMENT 속성을 모두 0.5로 설정하여 수평 및 수직 방향 모두 가운데 정렬이 되도록 하였습니다. 또한 각 셀 내에서의 문자의 표시 위치가 가운데가 되도록 하기 위하여 좌표값들을 모두 0.5 단위로 변경하였습니다. 그러면 결과는 다음 그림과 같습니다.

 

 

이러면 표를 구현하고 각 셀 내에 값들이 표시되도록 하는 과정은 어느 정도 마무리된 것 같습니다. 이제 마지막으로 표의 좌측 및 상단 테두리 부분(숫자들이 표시되지 않은)을 약간 진한 색으로 처리해봅시다. 이를 위한 방법으로서 다음과 같이 8x6의 구조를 갖는 가상의 2차원 배열을 생성하고 이를 이미지의 형태로 중첩하여 표출하고자 합니다.

 

tmp = MAKE_ARRAY(8, 6, VALUE=255B)
tmp[*, 5] = 200B
tmp[0, *] = 200B
im = IMAGE(tmp, /OVERPLOT)

 

여기서는 8x6의 구조를 갖는 tmp라는 배열을 생성하고 전체적으로 색상값이 0번 컬러테이블 기준으로 흰색(255B)이 되도록 하되 왼쪽 및 상단 테두리 부분만 회색(200B)이 되도록 처리한 후 IMAGE 함수를 사용하여 중첩 표출하는 방법을 사용하였습니다. 다만 한가지 유의할 것은 이 과정은 앞서 데이터 값들을 문자로 셀 내에 표시하는 과정보다 앞서서 실행되어야 한다는 것입니다. 그러지않으면 애써서 표시한 문자들을 이미지가 덮어버리기 때문입니다. 따라서 전체적인 과정은 다음과 같은 순서가 되어야 합니다.

 

y = INDGEN(11)
win = WINDOW(DIMENSIONS=[600, 500], /NO_TOOLBAR)
p = PLOT(y, XRANGE=[0, 8], YRANGE=[0, 6], $
  XTICKINTERVAL=1, YTICKINTERVAL=1, $
  XTICKLEN=1, YTICKLEN=1, XMINOR=0, YMINOR=0, $
  XSHOWTEXT=0, YSHOWTEXT=0, /NODATA, $
  MARGIN=0.1, /CURRENT)

tmp = MAKE_ARRAY(8, 6, VALUE=255B)
tmp[*, 5] = 200B
tmp[0, *] = 200B
im = IMAGE(tmp, /OVERPLOT)

data = INDGEN(7, 5)
FOR j = 0, 4 DO BEGIN
  FOR i = 0, 6 DO BEGIN
    t = TEXT(i+1.5, 6-j-1.5, STRING(data[i, j], FORMAT='(I0)'), $
      ALIGNMENT=0.5, VERTICAL_ALIGNMENT=0.5, FONT_SIZE=11, /DATA)
  ENDFOR
ENDFOR

 

그러면 결과는 다음 그림과 같습니다.

 

 

물론 여기서 좀 더 해본다면 테두리 부분에도 문자들을 삽입한다든지 하는 작업들이 더 필요할 수도 있습니다. 어차피 원하는 위치에 원하는 내용의 문자들을 삽입하는 방법은 위의 과정을 참조하여 처리할 수 있을 것입니다. 어쨌든 과정이 약간 복잡하긴 했지만, IDL에서도 표(Table)와 유사한 방식의 표출을 나름대로 해볼 수 있다는 하나의 예제로 봐주시면 될 것 같습니다.

반응형