정보
-
업무명 : 대기 환경 자료 처리 및 가시화 : HDF 형식인 전지구 오존량 자료를 이용한 가시화
-
작성자 : 이상호
-
작성일 : 2020-03-31
-
설 명 :
-
수정이력 :
내용
[개요]
-
안녕하세요? 기상 연구 및 웹 개발을 담당하고 있는 해솔입니다.
-
대기 환경 정보는 다양한 차원의 관측 자료 및 분석 자료로 구성되어 있기 때문에 이용자가 적절한 분석 및 가시화 기술이 요구됩니다.
-
따라서 오늘 포스팅에서는 HDF 형식인 전지구 오존량 자료를 이용한 가시화를 소개해 드리고자 합니다.
-
추가로 대기과학 전공자를 위한 IDL를 소개한 링크를 보내드립니다.
[특징]
-
대기 환경 자료를 이해하기 위해서 자료 처리 및 가시화 기술이 요구되며 이 프로그램은 이러한 목적을 달성하기 위해 고안된 소프트웨어
[기능]
-
위도, 경도, 전지구 오존량 자료 읽기
-
자료 전처리
-
가시화
[활용 자료]
-
자료명 : TOMS_AI_20051201.hdf
-
자료 종류 : 오존량 자료
-
확장자 : hdf
-
영역 : 전지구
-
기간 : 2005년 12월 01일 - 2005년 12월 28일
[사용법]
-
입력 자료를 동일 디렉터리에 위치
-
소스 코드를 실행 (idl -e Visualization_Using_Ozone_Data_of_HDF_Format)
-
가시화 결과를 확인
[사용 OS]
-
Windows 10
[사용 언어]
-
IDL v8.5
소스 코드
-
해당 작업을 하기 위한 컴파일 및 실행 코드는 IDL로 작성되었으며 가시화를 위한 라이브러리는 Coyote's Guide to IDL Programming를 이용하였습니다.
-
소스 코드는 단계별로 수행하며 상세 설명은 다음과 같습니다.
-
1 단계는 주 프로그램은 작업 경로 설정, HDF 파일 읽기, 변수 전처리하여 메모리상에 저장하고 가시화를 위한 초기 설정합니다.
-
2 단계는 plot 매핑에 따라 영상 장면 표출하여 이미지 형식으로 저장합니다. 이 과정에서 포스트 스크립트 (PS) 형식에서 PNG로 변환합니다.
-
[명세]
-
전역 변수 설정
-
cd를 통해 작업 디렉터리 설정
-
file_search를 통해 HDF 형식인 파일 목록 확인
-
위/경도, 오존량에 대한 배열 (dim) 설정
-
cd, 'C:\SYSTEM\PROG\IDL\HDF'
fileList = file_search("./INPUT/*.hdf", count = iNumber)
dim = [288, 180, iNumber]
lon1D = fltarr(dim[0])
lat1D = fltarr(dim[1])
val2D = fltarr(dim[0], dim[1])
val3D = fltarr(dim[0], dim[1], dim[2])
valMean2D = fltarr(dim[0], dim[1])
valSd2D = fltarr(dim[0], dim[1])
-
HDF 파일 읽기 및 전처리
-
반복문 및 hd_sd_getdata를 통해 2차원 전지구 오존량 (ozone) 읽기
-
즉 2차원 자료를 3차원으로 변환 (val3D)
-
for iCount = 0L, dim[2] - 1 do begin
hdf_file = fileList(iCount)
print, hdf_file
sd_id = hdf_sd_start(hdf_file, /read)
sds_name = "O3"
sds_index = hdf_sd_nametoindex(sd_id, sds_name)
sds_id = hdf_sd_select(sd_id,sds_index)
hdf_sd_getdata, sds_id, ozone
hdf_sd_endaccess, sds_id
hdf_sd_end, sd_id
val3D(*, *, iCount) = ozone(*, *)
endfor
-
위/경도 자료 설정
- findgen를 통해 288개 경도와 180개 위도 생성
lat1D = 89.5 - findgen(180)
lon1D = -179.375 + (findgen(288) * 1.25)
-
요약 통계량 확인
-
최소값 (min), 평균값 (mean), 최대값 (max) 계산
-
help를 통해 자료형 및 배열 정보 확인
-
print, min(lon1D, /nan), mean(lon1D, /nan), max(lon1D, /nan)
print, min(lat1D, /nan), mean(lat1D, /nan), max(lat1D, /nan)
print, min(val3D, /nan), mean(val3D, /nan), max(val3D, /nan)
help, lon1D, lat1D, val3D
-
가시화
-
데이터 세트에서 정보는 여전히 숨겨져 있기 때문에 가시화 필요
-
가시화는 일반적인 정적 탐색 데이터 분석에서 웹 브라우저의 동적 대화식 데이터 시각화에 이르기까지 다양함
-
-
전지구 오존량을 위한 설정 및 가시화
-
시간에 따른 반복문 수행
-
관심 영역 (ROI)과 중심 위/경도 (cnLon, cnLat) 설정
-
이미지 저장 파일명 (psName) 및 제목명 (mainName)
-
fnMakePsPlot를 통해 이미지 저장
-
for iCount = 0L, dim[2] - 1 do begin
hdf_file = fileList(iCount)
dateYmd = STRMID(hdf_file, 14, 8)
psName = "Img01_" + dateYmd
mainName = "HDF Ozone Amount : " + dateYmd
val2D = val3D[*, *, iCount]
fnMakePsPlot, lon1D, lat1D, val2D, dim, cnLat, cnLon, ROI, psName, mainName, 200, 500, 50, 33
endfor
-
2005년 12월에 전지구 오존량의 평균 및 표준편차를 위한 설정 및 가시화
-
시간에 따른 위/경도의 평균 (mean) 및 표준편차 (stddev) 반복문 수행
-
요약 통계량 확인
-
fnMakePsPlot를 통해 이미지 저장
-
for i = 0L, dim[0] - 1 do begin
for j = 0L, dim[1] - 1 do begin
valMean2D(i, j) = mean(val3D(i, j, *), /nan)
valSd2D(i, j) = stddev(val3D(i, j, *), /nan)
endfor
endfor
print, min(valMean2D, /nan), mean(valMean2D, /nan), max(valMean2D, /nan)
print, min(valSd2D, /nan), mean(valSd2D, /nan), max(valSd2D, /nan)
help, valMean2D, valSd2D
dateYmdPeriod = '20051201-20051228'
psName = "Img02_Mean_" + dateYmdPeriod
mainName = "HDF Mean Ozone Amount : " + dateYmdPeriod
fnMakePsPlot, lon1D, lat1D, valMean2D, dim, cnLat, cnLon, ROI, psName, mainName, 200, 400, 20, 33
psName = "Img03_Stdev_" + dateYmdPeriod
mainName = "HDF Stdev Ozone Amount : " + dateYmdPeriod
fnMakePsPlot, lon1D, lat1D, valSd2D, dim, cnLat, cnLon, ROI, psName, mainName, 0, 100, 20, 33
-
2005년 12월 01-28일 오존량 평균
-
2005년 12월 01-28일 오존량 표준편차
-
동영상 애니메이션 설정
-
반복문 수행한 이후 spawn를 통해 1초마다 동영상 애니메이션 생성
-
com = "convert -loop 0 -delay 100 "+ "./FIG/*.png" + " " + "./GIF/Img01.gif"
spawn, /hide, com
-
사용자 편의성 함수 정의
-
전달 인자
-
1차원 위도 (lon1D), 1차원 경도 (lat1D), 2차원 값 (val2D), 배열 정보 (dim), 중심 위도 (cnLat), 중심 경도 (cnLon), 관심 영역 (ROI), 이미지 저장 파일명 (psName), 제목명 (mainName), 최소값 (zmin), 최대값 (zmax), 등고선 간격 (interval), 컬러 테이블 (color_table)
-
-
기능
-
plot를 통해 위/경도에 따른 값 매핑
-
포스트 스크립트 (PS)를 PNG로 변환
-
-
;====================================================================
; Subroutine : Function Make Postscript to Png Graph
;====================================================================
pro fnMakePsPlot, lon1D, lat1D, val2D, dim, cnLat, cnLon, ROI, psName, mainName, zmin, zmax, interval, color_table
set_plot, "ps"
device, filename = psName + ".ps", decomposed = 0, bits = 8, /color, xsize = 20, ysize = 9, /inches, font_size = 13, /Helvetica
!p.font = 0 & !p.charsize = 2.0 & !p.charthick = 1.6 & !p.multi = [0,1,1] & !p.background = 255
xvert = [0.1, 0.1, -0.1, -0.1 ,0.1]
yvert = [-0.1, 0.1, 0.1, -0.1, -0.1]
usersym, xvert, yvert, /fill
start_color = 0 & end_color = 255 & colorn = end_color - start_color + 1
cgloadct, color_table
latmin = ROI(0) & latmax= ROI(1) & lonmin = ROI(2) & lonmax= ROI(3)
cgMAP_SET, cnLat, cnLon, /CYLINDRICAL $
, limit = [latmin, lonmin, latmax, lonmax] $
, position = [0.05, 0.0, 0.85, 0.90], /noborder, /ISOTROPIC
for i = 0L, dim[0] - 1 do begin
for j = 0L, dim[1] - 1 do begin
nLon = lon1D[i]
nLat = lat1D[j]
nVal = val2D[i, j]
if (lonmin gt nLon or nLon gt lonmax or finite(nLon, /nan) eq 1) then continue
if (latmin gt nLat or nLat gt latmax or finite(nLat, /nan) eq 1) then continue
if (finite(nVal, /nan) eq 1) then continue
plots, nLon, nLat, psym = 8, symsize = 14, color = BYTSCL(nVal, zmin, zmax)
endfor
endfor
cgColorbar, NColors = 255, BOTTOM = 1 $
, Divisions = 5, COLOR = "black" $
, Position = [0.1, 0.90, 0.8, 0.94] $
, Range = [zmin, zmax] $
, CHARSIZE = 1.5,CHARthick = 2 $
, VERTICAL = 1, RIGHT = 1, Format = "(i3)"
cgLoadct, 2
contour, val2D, lon1D, lat1D, /overplot, C_THICK = 2 $
, LEVELS = zmin + findgen(10) * interval $
, C_LABELS = zmin + findgen(10) * interval $
, C_CHARSIZE = 1.5, C_CHARTHICK = 2 $
, C_COLORS = BYTSCL(zmin + findgen(10) * interval, zmin, zmax)
cgMAP_CONTINENTS, /coast, /countries, COLOR = "black"
lats = [-90:90:30]
lons = [-180:360:60]
lats_names = strarr(n_elements(lats))
lons_names = strarr(n_elements(lons))
for i = 0L, n_elements(lats) - 1 do begin
if (lats[i] gt 0) then begin
lats_names[i] = textoidl(string(lats[i]) + "\circN")
endif else if (lats[i] eq 0) then begin
lats_names[i] = textoidl(string(lats[i]) + "\circ")
endif else begin
lats_names[i] = textoidl(string(-lats[i]) + "\circS")
endelse
endfor
for i = 0L,n_elements(lons) - 1 do begin
if (lons[i] gt 0) then begin
lons_names[i] = textoidl(string(lons[i]) + "\circE")
endif else if (lons[i] eq 0) then begin
lons_names[i] = textoidl(string(lons[i]) + "\circ")
endif else begin
lons_names[i] = textoidl(string(-lons[i]) + "\circW")
endelse
endfor
cgMap_grid, color = "black", charsize = 1.8, thick = 2.5, lats = lats, latnames = lats_names, lons = lons, lonnames = lons_names $
, linestyle = 1, bthick = 300, /box_axes, /no_grid
cgText, 0.45, 0.95, mainName, /normal, charsize = 2, CHARTHICK = 2, color = 0, alignment = 0.5
device, /close_file
com = "convert -flatten -background white " + psName + ".ps" + " " + "./FIG/" + file_basename(psName, ".ps") + ".png"
spawn, /hide, com
file_delete, ps_name + ".ps"
return
end
[전체]
참고 문헌
[논문]
- 없음
[보고서]
- 없음
[URL]
- 없음
문의사항
[기상학/프로그래밍 언어]
- sangho.lee.1990@gmail.com
[해양학/천문학/빅데이터]
- saimang0804@gmail.com
최근댓글