IDL/Programming

기상청 ASOS 자료의 공간 분포 표출 [3]

이상우_IDL 2025. 2. 4. 15:43
728x90

지난 회차 게시물들(링크 1, 링크 2)에서는 기상청 ASOS 장비의 기상요소 관측자료를 기상자료 개방포털 웹페이지에서 CSV 파일로 수신한 다음 이 파일을 IDL에서 읽고 처리하여 특정한 시각에 대한 모든 지점들의 기온 값을 한반도 지도상에 표출하는 과정을 살펴본 바 있습니다. 또한 지점별로 존재하는 기온 값들에 대하여 Kriging 기법을 적용하여 일정한 경위도 범위의 격자 데이터로 환산하여 표출하는 과정도 이어서 살펴보았습니다. 이와 같이 이전 게시물들에서는 기상요소들 중 기온에 중점을 두고 살펴보았는데요. 그 외에도 습도나 기압 등과 같은 기상요소들도 유의미한 값 범위는 좀 다르겠지만 표출 방식 자체는 본질적으로 크게 다르지 않습니다. 따라서 처리 및 표출 과정은 기온에 대한 예제를 살짝 수정하면 됩니다.

 

그런데 바람 자료 즉 풍속과 풍향의 경우는 그 특성상 처리 및 표출의 방식이 앞선 기상요소들과는 조금 다릅니다. 왜냐하면 크기 뿐 아니라 방향성도 함께 고려되어야 하는 기상요소이기 때문입니다. 따라서 이러한 특성을 감안하여 바람 자료를 처리하고 각 지점별로 풍향 및 풍속을 한반도 지도상에 표출하는 과정을 살펴보고자 합니다. 먼저 자료 파일은 지난 회차 게시물들에서 사용했던 CSV 파일을 그대로 사용합니다.

 

OBS_ASOS_TIM_20250108162821.csv
0.25MB

 

그 다음은 이 파일을 READCOL 명령으로 읽어서 필요한 배열들을 가져오는 과정인데, 이번에는 풍속 및 풍향 값들이 그 대상이기 때문에 READCOL 명령의 내용이 다음과 같이 변경되어야 합니다.

 

file = 'OBS_ASOS_TIM_20250108162821.csv'
READCOL, file, stnids, dstrs, wss, wss_qc, wds, wds_qc, $
  FORMAT='I,X,A,X,X,F,I,F,I', DELIMITER=',', /NAN, /PRESERVE_NULL
HELP, stnids, dstrs, wss, wss_qc, wds, wds_qc

 

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

 

STNIDS          INT       = Array[4753]
DSTRS           STRING    = Array[4753]
WSS             FLOAT     = Array[4753]
WSS_QC          INT       = Array[4753]
WDS             FLOAT     = Array[4753]
WDS_QC          INT       = Array[4753]

 

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

 

dstr = '2025-01-03 01:00'
ww = WHERE(dstrs EQ dstr, count)
stnids = stnids[ww]
wss = wss[ww]
wss_qc = wss_qc[ww]
wds = wds[ww]
wds_qc = wds_qc[ww]
HELP, stnids, wss, wss_qc, wds, wds_qc

 

이러한 추출 과정을 거치면 2025년 1월 3일 01시라는 특정한 시각에 대한 모든 지점들의 값들만 추출될 것입니다. HELP에 의하여 출력된 정보를 보면 총 97개의 값들이 추출된 것을 알 수 있습니다. 그리고 결측 데이터를 걸러내기 위하여 QC 플래그 즉 품질 번호가 9가 아닌 경우들만 추출하는 과정이 필요합니다. 이를 위하여 다음과 같이 WHERE 함수를 사용하여 풍속에 대한 플래그가 9가 아닌 경우들만 선별하는 인덱싱 작업을 진행합니다. 이 때 풍속 플래그 대신 풍향 플래그를 대상으로 해도 될 것 같습니다. 아마도 풍속과 풍향에 대한 품질 플래그는 동일하다고 가정해도 될 것 같기 때문입니다.

 

wgood = WHERE(wss_qc NE 9, cgood)
wss_good = wss[wgood]
wds_good = wds[wgood]

 

그리고 우리가 이전에 이미 저장해두었던 ASOS_stations.sav 파일에 수록된 배열들을 RESTORE 명령으로 불러와서 ASOS 지점들의 경도 및 위도 값들을 담은 배열에 대해서도 동일한 인덱싱 작업을 진행합니다.


RESTORE, 'ASOS_stations.sav'
lons_good = lons[wgood]
lats_good = lats[wgood]

 

이와 같은 과정들을 거쳐서 wss_good, wds_good, lons_good, lats_good 배열들을 얻게 됩니다. 다음과 같이 HELP 명령을 사용하면 이 배열들이 각각 97개의 값들로 구성된 것을 확인할 수 있습니다.


HELP, wss_good, wds_good, lons_good, lats_good

 

WSS_GOOD        FLOAT     = Array[97]
WDS_GOOD        FLOAT     = Array[97]
LONS_GOOD       FLOAT     = Array[97]
LATS_GOOD       FLOAT     = Array[97]

 

일단 이 결과를 보면 이 시각(2025년 1월 3일 01시)에 대해서는 결측 데이터가 발생한 지점은 없는 것으로 확인됩니다. 이제 이 배열들을 이용하여 바람 데이터를 한반도 지도상에 표출하는 과정으로 넘어가면 됩니다. 일단 지도 표출 작업은 이전과 동일한 방식으로 다음과 같이 진행합니다.

 

win = WINDOW(DIMENSIONS=[800, 850], /NO_TOOLBAR)
m = MAP('Geographic', LIMIT=[33, 124, 40, 131], FONT_SIZE=11, $
  MARGIN=[0.07, 0.05, 0.07, 0.10], /CURRENT)
mc = MAPCONTINENTS(/HIRES, FILL_COLOR=[240, 240, 240])
m.MapGrid.LINESTYLE = 1
m.MapGrid.LABEL_POSITION = 0
m.MapGrid.HORIZON_LINESTYLE = 0

 

이제 바람 데이터를 지도상에 표시하는 방식을 좀 생각해봐야 합니다. 아무래도 풍속과 풍향이라는 요소들이라는 점을 감안한다면 각 지점별 위치에 풍향 및 풍속을 반영하는 벡터 화살표를 표시하는 방식을 생각해볼 수 있습니다. 이러한 작업은 VECTOR 함수를 사용하여 처리할 수 있습니다. VECTOR 함수의 사용법에 관해서는 이전에 관련 게시물들(링크 1, 링크 2)을 올린 바 있으며 기본적으로는 이 내용을 참조하기로 합니다. 여기서 가장 중요하게 유념해야 할 것은 VECTOR 함수는 다음과 같이 벡터의 U, V 성분 값들로 구성된 배열을 인수로 받는다는 것입니다.

 

graphic = VECTOR(u, v, x, y, ~~~)

 

즉 이러한 문법에 의하여 벡터의 U성분, V성분, 위치의 X좌표, Y좌표에 해당되는 배열을 인수로 투입해야 합니다. 그런데 우리가 확보한 바람 자료의 경우는 풍속 및 풍향인데 이것은 벡터의 길이 및 각도에 해당된다고 볼 수 있습니다. 즉 현재 우리가 갖고 있는 풍향 및 풍속 데이터 자체는 U, V 성분 데이터가 아님을 유념해야 합니다. 따라서 풍향 및 풍속으로 구성된 데이터를 U, V 성분 데이터로 환산해주는 작업이 반드시 필요합니다. 그리고 여기서 고려해야 할 또 한가지 중요한 사항은 풍향의 각도를 산정하는 방식이 기상학적(Meteorological) 방식이라는 점입니다. 따라서 풍향의 각도가 이러한 기준에 의한 값들임을 감안해야 합니다. 이와 같은 이슈에 관한 자세한 내용은 관련 게시물을 참조하는 것으로 하고 여기서는 자세한 설명은 생략하겠습니다. 그러면 작업을 계속 진행해서 풍속 및 풍향 데이터를 U, V 성분 데이터로 변환하는 과정을 다음과 같이 처리합니다.

 

uu = -wss_good*SIN(wds_good*!DTOR)
vv = -wss_good*COS(wds_good*!DTOR)

 

이와 같은 방식으로 U 및 V 성분값들로 구성된 배열들인 uu 및 vv를 얻을 수 있습니다. 사실 이와 같이 풍속 및 풍향의 형태로 구성된 바람 데이터를 U, V 성분 값들로 환산하는 작업은 VECTOR 함수가 그러한 형태를 요구하기 때문인 것만은 아닙니다. 작업을 진행하다보면 벡터 형태의 값들을 대상으로 이런저런 계산 과정을 거치게 될 수도 있는데, 어차피 이러한 다양한 수학적 계산 과정을 위해서는 U, V 성분 값들이 반드시 필요합니다. 이러한 필요성은 우리가 나중에 하게 될 작업에서 확인할 수 있습니다. 어쨌든 앞서 우리가 지도를 이미 표출해둔 상태이므로 이제 VECTOR 함수를 사용하여 지도상에 바람 벡터들을 표시해봅시다. 그 과정은 다음과 같이 처리해봅니다.

 

vec = VECTOR(uu, vv, lons_good, lats_good, THICK=2, $
  HEAD_SIZE=1, DATA_LOCATION=2, LENGTH_SCALE=MAX(wss_good)/5., $
  COLOR='crimson', /OVERPLOT)

 

이와 같이 VECTOR 함수에는 앞서 얻었던 U, V 성분값 배열들인 uu, vv 그리고 각 벡터의 좌표값 배열들인 lons_good, lats_good이 차례로 인수로 투입되었습니다. 여기서 LENGTH_SCALE 속성에 대해서는 풍속의 최대값(여기서는 9.4)을 5로 나눈 값을 투입하여 벡터 화살표들의 전반적인 길이 스케일을 설정해보았습니다. 그리고 DATA_LOCATION 속성의 값을 2로 설정한 것은 벡터 화살표의 끝부분이 각 지점 위치가 되도록 하기 위한 것인데, 원래 풍향 데이터가 그 지점으로 불어오는 바람의 방향을 기준으로 한다는 점을 고려한 것입니다. 대략 이와 같은 방식으로 처리하면 한반도 지도상에 바람 벡터들이 각 지점마다 화살표의 형태로 표시됩니다. 표출 결과는 다음 그림과 같습니다.

 

이 그림을 보면 일단 우리가 의도했던 방식의 표출은 된 것 같습니다. 다만 여기서 좀 더 손질을 해보자면 각 지점의 위치도 별도의 기호로 따로 표시해주는 것이 좋을 것 같습니다. 이를 위하여 다음과 같이 SCATTERPLOT 함수를 사용하여 각 지점을 원형 기호로 표시해주면 어떨까 합니다.

 

sp = SCATTERPLOT(lons_good, lats_good, SYMBOL='circle', /SYM_FILLED, $
  SYM_SIZE=0.5, SYM_COLOR='green', /OVERPLOT)

 

이와 같이 해주면 다음과 같이 각 지점의 위치마다 원형 기호들이 표시될 것입니다.

 

그리고 이번에는 벡터 화살표의 길이에 대한 기준값을 표시해봅시다. 즉 그림에서 보이는 벡터들의 길이가 다양한데 각각의 길이가 어느 정도의 풍속에 해당되는가를 가늠할 수 있도록 하기 위한 것입니다. 지도 상의 우측 상단에 기준 화살표가 표시되도록 하기 위하여 다음과 같이 VECTOR 함수를 사용해봅시다.

 

vec_ref = VECTOR([10], [0], [130.5], [39.5], THICK=2, $
    HEAD_SIZE=1, LENGTH_SCALE=MAX(wss_good)/5, $
    COLOR='crimson', /OVERPLOT)

tx_ref = TEXT(130.5, 39.3, '10(m/s)', ALIGNMENT=0.5, /DATA)

tx = TEXT(0.5, 0.93, dstr+', Wind Vectors', ALIGNMENT=0.5, FONT_SIZE=16, /NORMAL)

 

여기서는 지도 상에서 경도 및 위도가 130.5 및 39.5인 위치에 풍속 10(m/s)에 해당되는 벡터 화살표가 수평 방향으로 표시되도록 한 것입니다. 또한 화살표 바로 밑에 해당 풍속 값을 나타내기 위하여 TEXT 함수를 사용하여 캡션 문자도 삽입하였습니다. 그 외에도 그림의 상단에 적절한 내용의 타이틀 문자도 표시되도록 해보았습니다. 이러한 과정들까지 모두 실행된 결과는 다음 그림과 같습니다.

 

일단 이와 같은 표출 결과를 얻었는데요. 물론 이 상태로 완벽하다고 볼 수는 없고 여러가지 측면에서 개선의 여지는 있습니다. 일단 벡터 화살표들을 보면 풍속의 크기에 따라 그 길이가 다양한데, 그러면서도 화살 머리의 크기는 고정된 상태입니다. 따라서 길이가 짧은 화살표의 경우는 머리만 너무 큰 경우들도 많이 보입니다. 이런 경우에는 VECTOR 함수가 사용되었던 내용에서 다음과 같이 HEAD_PROPORTIONAL 키워드를 추가하여 각 벡터마다 화살 머리의 크기가 화살의 길이에 비례하도록 하는 방법도 있습니다.

 

vec = VECTOR(uu, vv, lons_good, lats_good, THICK=2, $
  HEAD_SIZE=1, DATA_LOCATION=2, LENGTH_SCALE=MAX(wss_good)/5, $
  COLOR='crimson', /HEAD_PROPORTIONAL, /OVERPLOT)

 

이러한 변경사항을 반영하여 다시 실행해보면 그 결과는 다음 그림과 같습니다.

 

물론 어떤 방식으로 화살표들이 표시되는 것이 좋은가에 대한 판단은 어디까지나 유저의 몫입니다. 그리고 이외에도 여러가지 개선 및 변경 사항들을 고려해볼 수도 있겠지만, 한반도 지도상에서 각 지점별로 풍속 및 풍향을 벡터의 형태로 표시하는 방법에 관해서는 일단 이 정도로 소개해봅니다.

 

 

 

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

LIST