IDL/Programming

기상청 ASOS 자료의 지점별 시계열 표출

이상우_IDL 2025. 1. 14. 14:45
728x90
반응형

지난 회차 게시물에서는 기상청 ASOS 장비의 지점 분포에 관한 메타 자료를 기상자료 개방포털 웹페이지에서 CSV 파일로 수신하여 IDL에서 읽고 처리하여 지점별 분포 현황을 가시화하는 과정을 관련 예제와 함께 소개한 바 있습니다. 오늘은 ASOS 장비에서 관측된 각종 기상요소 관측값들에 대한 자료를 역시 동일한 웹페이지에서 수신하여 IDL에서 처리 및 가시화하는 작업을 시도해보고자 합니다. ASOS의 기상관측자료를 수신하는데 있어서는 일정한 기간을 정하고 그 기간 동안 ASOS 모든 지점에서 관측된 기상요소 값들이 수록된 CSV 파일의 형태로 얻어봅시다. 이를 위해서는 기상자료 개방포털 웹페이지의 해당 섹션에서 필요한 설정을 하여 자료 파일을 수신하면 됩니다.

 

즉 이와 같이 종관기상관측(ASOS) 자료 섹션에서 지점은 전체로 설정하고 필요한 기상요소들을 체크하면서 기간을 적절히 설정해준 다음 CSV 버튼을 누르면 됩니다. 위의 예를 보면 먼저 기간은 2025년 1월 3일 00시부터 1월 5일 00시까지로 설정하였습니다. 그리고 기상요소들은 기온, 바람, 습도를 체크하였습니다. 관측값들의 시간 간격은 1시간입니다. 이렇게 하면 ASOS 97개 전 지점들에 대하여 2025년 1월 3일 00시부터 1월 5일 00시까지 기온, 바람(풍향 및 풍속), 습도 관측값들이 1시간 간격으로 수록된 CSV 파일을 얻을 수 있습니다. 제가 실제로 이러한 방식으로 입수한 CSV 파일을 엑셀로 열어본 모습은 다음과 같습니다. 물론 전체 내용은 꽤 길기 때문에 극초반부만 본 모습입니다.

 

참고로 제가 얻었던 이 CSV 파일은 아래에 첨부해놓습니다.

 

OBS_ASOS_TIM_20250108162821.csv
0.25MB

 

위의 스크린샷을 보면 여러 컬럼들이 보이는데 오늘 할 작업에서 중요한 컬럼들은 지점번호(컬럼 1), 날짜(컬럼 3)을 비롯하여 그 뒤에 이어지는 각 기상요소별 컬럼들이 될 것입니다. 그러면 여러 기상요소들 중 기온을 그 대상으로 정하고 지금부터 작업을 시작해봅시다. 이 작업은 특정한 ASOS 지점을 정해서 그 지점의 기온 관측값들의 시계열 변화를 가시화하는 작업이 될 것입니다. 일단 가장 먼저 해야 할 일은 지난 회차 게시물에서 ASOS 지점 정보들을 저장했던 .sav 파일을 불러오는 것입니다.

 

ASOS_stations.sav
0.00MB

 

num = 127
RESTORE, 'ASOS_stations.sav'
ww = WHERE(numbers EQ num, count)
lon = lons[ww]
lat = lats[ww]
name = names[ww]

 

여기서 num은 대상이 될 지점의 번호인데 여기서는 127번 충주 지점으로 지정해보았습니다. 그리고 ASOS_stations.sav 파일에 대하여 RESTORE 명령을 사용하면 그 파일 내에 저장되어있는 lons, lats, names 등의 배열들을 가져올 수 있습니다. 그 다음에는 WHERE 함수를 사용하여 이 지점의 경도, 위도, 지점명 값들을 추출하여 lon, lat, name 변수들에 담아두었습니다. 이 정보들은 나중에 활용될 예정입니다. 그 다음에는 전체 데이터가 수록된 CSV 파일로부터 데이터를 읽는 과정인데, 지난 회차 게시물과 마찬가지로 READCOL 명령을 사용하여 다음과 같이 처리합니다.

 

file = 'OBS_ASOS_TIM_20250108162821.csv'
READCOL, file, stnids, dstrs, temps, temps_qc, $
  FORMAT='I,X,A,F,I', DELIMITER=',', /NAN, /PRESERVE_NULL
HELP, stnids, dstrs, temps, temps_qc

 

이렇게 하면 CSV 파일 내에 수록된 모든 지점번호, 날짜, 기온, 기온 플래그 값들을 담은 배열들인 stnids, dstrs, temps, temps_qc를 얻게 됩니다. HELP에 의하여 출력된 정보를 보면 다음과 같습니다.

 

STNIDS          INT       = Array[4753]
DSTRS           STRING    = Array[4753]
TEMPS           FLOAT     = Array[4753]
TEMPS_QC        INT       = Array[4753]

 

이와 같이 각 배열은 4753개의 값들로 구성됩니다. 앞서 언급했듯이 CSV 파일 내에 수록된 모든 데이터 즉 전체 시간 및 전체 지점들에 대한 데이터를 모두 읽었기 때문입니다. 하지만 후속 작업에서는 대상이 될 하나의 지점에 대한 데이터만 필요하기 때문에 별도의 과정을 거쳐 이러한 데이터만 따로 추출하는 것이 필요합니다. 그 과정은 다음과 같이 처리해봅시다.

 

ww = WHERE(stnids EQ num AND temps_qc NE 9, count)
IF count NE 0 THEN BEGIN
  dstrs = dstrs[ww]
  temps = temps[ww]
ENDIF
HELP, dstrs, temps

 

이와 같이 WHERE 함수를 사용하여 지점번호를 특정하여 추출하면 됩니다. 즉 stnids 배열 내에는 97개 모든 지점들의 지점번호 값들이 존재하기 때문에 이들 중에서 그 번호가 num과 동일한 경우들만 선별한 것입니다. 그리고 temps_qc 배열은 기온값에 대한 품질 체크 고유 번호들을 담고 있는데 이 번호가 9인 경우는 결측(값이 없는 경우)에 해당됩니다. 따라서 결측인 경우들을 제외하는 것도 필요합니다. 이러한 선별 조건들을 WHERE 함수 내에서 명시하여 필요한 항목들만 추려내면 각 배열은 총 49개의 값들로 구성될 것입니다. HELP에 의하여 출력된 정보에서 이를 확인할 수 있습니다.

 

DSTRS           STRING    = Array[49]
TEMPS           FLOAT     = Array[49]

 

그 다음에는 문자형 값으로 존재하는 날짜 데이터를 줄리안 날짜(Julian Date)의 형태로 변환하는 과정이 필요합니다. 이것은 나중에 데이터를 시계열 플롯으로 표출하는데 있어서 X축이 날짜가 되어야 하기 때문에 이를 위한 준비 과정이라고 보면 됩니다. 이러한 작업은 날짜 정보를 담은 문자열에서 년, 월, 일, 시, 분 값들을 추출하여 JULDAY 함수에 투입하는 방식으로 처리합니다. 일단 이러한 문자열은 다음과 같은 형태를 띕니다.

 

2025-01-03 05:00

 

이 문자열에서 년(year)은 처음부터 네번째 문자, 월(month)은 6번째부터 7번째 문자 등과 같이 위치합니다. 이러한 방식으로 dstrs 배열에 대하여 STRMID 함수를 사용하여 각 위치별로 년, 월, 일, 시, 분 값들을 담은 배열을 뽑아내고 이들을 JULDAY 함수에 투입하면 됩니다. 이 과정은 다음과 같이 처리합니다.

 

years = FIX(STRMID(dstrs, 0, 4))
months = FIX(STRMID(dstrs, 5, 2))
days = FIX(STRMID(dstrs, 8, 2))
hours = FIX(STRMID(dstrs, 11, 2))
minutes = FIX(STRMID(dstrs, 14, 2))
tjs = JULDAY(months, days, years, hours, minutes, 0)

이렇게 얻어진 tjs는 49개의 줄리안 날짜 값들로 구성된 배열이 될 것입니다. 그리고 나중에 표출할 시계열 플롯의 X축의 범위를 결정할 두 날짜 값들도 다음과 같은 방식으로 정의해두는 것이 좋습니다. 이 값들은 나중에 플롯 그림을 표출할 때 XRANGE 속성에 투입될 것입니다.

 

tj1 = JULDAY(1, 3, 2025, 0, 0, 0)

tj2 = JULDAY(1, 5, 2025, 0, 0, 0)

 

이제는 데이터를 시계열 플롯의 형태로 가시화하는 단계로 넘어가면 됩니다. 여기서는 가로 방향이 직사각형 모양의 그래픽창을 띄우고, 우측에는 기온에 대한 시계열 플롯을 표출하고 좌측에는 해당 지점의 이름 및 위치가 표시된 지도를 표출하는 방식으로 작업을 해보고자 합니다. 그러면 먼저 그래픽창을 띄우고 시계열 플롯을 적절한 위치에 표출하는 과정부터 보면 대략 다음과 같습니다.

 

win = WINDOW(DIMENSIONS=[1200, 500], /NO_TOOLBAR)
dummy = LABEL_DATE(DATE_FORMAT=['%M %D!C%H:%I!C%Y'])
p = PLOT(tjs, temps, COLOR='blue', YRANGE=[-10, 10], $
  XRANGE=[tj1, tj2], XTICKUNITS='hour', XTICKINTERVAL=6, XMINOR=5, $
  SYMBOL='circle', /SYM_FILLED, LINESTYLE=6, $
  XTICKFORMAT='label_date', YTITLE='Temperature ('+'$\deg$'+'C)', $
  MARGIN=[0.44, 0.1, 0.03, 0.1], CLIP=0, /CURRENT)

 

시계열 플롯의 경우는 X축이 날짜가 되어야 하므로 LABEL_DATE 함수를 적절히 활용하였습니다. 그리고 X축의 범위를 설정하는데 있어서는 앞서 얻었던 tj1, tj2를 이용하였습니다. Y축의 범위는 겨울철의 기온임을 감안하여 -10~10으로 설정하였고, 좌측의 여백을 좀 크게 잡아서 나중에 지도가 위치할 공간을 확보하였습니다. 일단 여기까지의 과정에 의하여 표출된 그림의 모습은 다음과 같습니다.

 

다음은 좌측 여백에 지도를 표시할 차례입니다. 지도를 표시하는 기본적인 과정 자체는 지난 회차 게시물에서 소개된 내용과 거의 유사합니다. 다만 이번에는 대상 지점 하나만 지도 상에 표시하기로 합니다. 이 과정은 다음과 같이 처리해봅시다.

 

m = MAP('Geographic', LIMIT=[33, 124, 40, 131], $
  POSITION=[0.03, 0.1, 0.35, 0.9], $
  ASPECT_RATIO=0, /CURRENT)
mc = MAPCONTINENTS(/HIRES, FILL_COLOR='light gray')
m.MapGrid.LINESTYLE = 1
m.MapGrid.LABEL_POSITION = 0
m.MapGrid.HORIZON_LINESTYLE = 0
sp = SYMBOL(lon, lat, SYMBOL='circle', /SYM_FILLED, $
  SYM_SIZE=1, SYM_COLOR='crimson', /DATA, TARGET=m)
str = name+'('+STRING(num, FORMAT='(I0)')+')'
tx = TEXT(lon, lat+0.12, str, ALIGNMENT=0.5, $
  /FILL_BACKGROUND, FILL_COLOR='yellow', $
  FONT_SIZE=11, FONT_NAME='Malgun', /DATA, TARGET=m)

 

여기서는 그래픽창의 좌측에 지도를 먼저 표시하고 그 다음에는 SYMBOL 및 TEXT 함수를 사용하여 대상 지점의 위치에 원형 기호 및 지점명을 추가하도록 하였습니다. 지점명을 한글 폰트로 표시하는 방식도 지난 회차 게시물에서 했던 것과 동일합니다. 이 과정까지 모두 실행된 결과는 다음 그림과 같습니다.

 

이와 같이 특정한 지점을 정해놓고 그 지점에 대한 기온 값의 시계열 변화를 플롯의 형태로 나타내면서 그 지점의 위치도 지도와 함께 표시할 수 있습니다. 만약 다른 지점에 대한 결과를 보려면 맨 처음에 정의했던 num 변수의 값만 원하는 지점의 번호로 변경해주면 됩니다. 예를 들어 다음과 같이 그 값을 101로 변경하여 전체 과정을 다시 실행하면 춘천 지점에 대한 결과 그림을 얻을 수 있습니다.

 

num = 101

 

그리고 262로 변경하면 고흥 지점에 대한 결과 그림을 얻을 수 있습니다.

 

num = 262

 

이상과 같이 기상자료 개방포털에서 CSV 파일의 형태로 입수한 ASOS 기상관측자료를 IDL에서 처리하여 지점별 시계열 플롯으로 표출하는 방식에 대한 예제를 소개해보았습니다. 만약 기온이 아닌 다른 기상요소를 대상으로 하게 될 경우에는 READCOL 명령에서 해당 컬럼을 읽도록 변경을 해줘야 하며, 시계열 플롯의 표출에 있어서도 Y축의 범위 등이 그 기상요소의 특성에 맞도록 변경해줘야 할 것입니다.

 

오늘 소개된 내용에서는 지점을 고정하고 시계열 플롯으로 데이터를 표출해보았는데, 이제 다음 회차에서는 시각을 고정하고 그 시각의 모든 지점들에 대한 데이터를 공간 분포의 형태로 표출하는 방법을 다뤄볼 예정입니다.

 

 

 

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

반응형