정보
-
업무명 : 그라즈 텍스트 (CSV) 형식인 ECMWF 해수면 온도 자료를 이용한 자료 처리 (Grid, Binary, Ctl, Map) 및 시각화
-
작성자 : 이상호
-
작성일 : 2020-07-05
-
설 명 :
-
수정이력 :
내용
[개요]
-
안녕하세요? 기상 연구 및 웹 개발을 담당하고 있는 해솔입니다.
-
GrADS는 텍스트 자료를 이용하여 직접적인 시각화하기 하기 어렵기 때문에 그에 따른 자료 처리 기술이 요구됩니다.
-
따라서 오늘 포스팅에서는 텍스트 (CSV) 형식인 ECMWF 해수면 온도 자료를 이용한 자료 처리 (Grid, Binary, Ctl, Map) 및 시각화를 소개해 드리고자 합니다.
-
추가로 오프라인 환경에서 GrADS 설치 및 공용 라이브러리 설정 방법을 소개한 링크를 보내드립니다.
-
추가로 그라즈 텍스트 (CSV) 형식인 ECMWF 해수면 온도 자료를 이용한 단번에 자료처리 (Text) 및 시각화를 소개한 링크를 보내드립니다.
[특징]
-
GrADS를 통해 시각화하기 위해서 자료 처리 기술이 요구되며 이 프로그램은 이러한 목적을 달성하기 위해서 고안된 소프트웨어
[기능]
-
임의 1 km 해상도 격자화 구성 및 Ctl 생성
-
위/경도에 따른 텍스트를 이용하여 바이너리 출력 및 Ctl 생성
-
격자에 대한 위/경도 내삽을 통한 시각화
[활용 자료]
-
자료명 : sst.txt
-
자료 종류 : 일평균 해수면 온도
-
확장자 : txt
-
영역 : 대한민국 한반도
-
기간 : 2019년 01월 01일 - 2019년 01월 31일
-
공간 해상도 : 25 km
[자료 처리 방안 및 활용 분석 기법]
-
없음
[사용법]
-
입력 자료를 동일 디렉터리에 위치
-
소스 코드를 실행 (bash RunShell.sh)
-
가시화 결과 확인
[사용 OS]
-
Linux (CentOS v7.3)
-
VMware Workstation Pro v15.5
[사용 언어]
-
GrADS v2.1.1
-
Shell Script (Bash)
-
Fortran
소스 코드
-
해당 작업을 하기 위한 컴파일 및 실행 코드는 GrADS, Shell Script, Fortran으로 작성되었으며 시각화를 위한 라이브러리는 kodama Library를 이용하였습니다.
-
작업 환경의 경우 5개 디렉터리로 구성되며 주 프로그램은 RunShell.sh로 구성되어 있습니다.
-
소스 코드는 단계별로 수행하며 상세 설명은 다음과 같습니다.
-
1 단계는 유용한 쉘 스크립트 함수 (로그 기록, 종료 코드 검사)를 초기 설정합니다.
-
2 단계는 작업 경로 및 필요한 라이브러리 경로를 설정합니다.
-
3 단계는 텍스트 (CSV) 파일을 소프트웨어에 입력하기 용이한 형태로 변환합니다.
-
4단계는 정적 소스 코드에 대한 Template를 생성합니다.
-
5단계는 동적 변수에 대한 변경 그리고 Fortran을 컴파일/실행하여 메모리상에 저장하고 가시화를 위한 초기 설정합니다.
-
6 단계는 ctl에 따라 영상 장면 표출하여 이미지 형식으로 저장합니다. 이 과정에서 포스트 스크립트 (EPS) 형식에서 PNG로 변환합니다.
-
[명세]
-
[1 단계] 유용한 쉘 스크립트 함수를 초기 기록
-
로그 레벨 (silent, notify, ok, warn, info, debug, error, crit)에 따른 컬러 부여
-
실행 명령어에 대한 경고/종료 코드 검사
-
세부 내용은 다음을 참조하시기 바랍니다.
-
#================================================
# Function
#===============================================
source ~/.DefaultCommon.sh
#------------------
# Log Level Print
#------------------
# silent ""
# notify ""
# ok ""
# warn ""
# info ""
# debug ""
# error ""
# crit ""
#------------------
# Exit Code Check
#------------------
# fnCheckWarn "$?"
# fnCheckExit "$?"
!/bin/bash
# color
colBlk='\033[0;30m' # Black Default
colRed='\033[0;31m' # Red
colGrn='\033[0;32m' # Green
colYlw='\033[0;33m' # Yellow
colPur='\033[0;35m' # Purple
colBlu='\033[0;34m' # Blue
colCya='\033[0;36m' # Cyan
colRst='\033[0m' # Text Reset
verbosity=6
# verbosity levels
sil_lvl=0
crt_lvl=1
err_lvl=2
wrn_lvl=3
ntf_lvl=4
inf_lvl=5
dbg_lvl=6
# esilent prints output even in silent mode
function silent() { verb_lvl=$sil_lvl log "${colCya}[SILE ]${colRst} $@" ; }
function notify() { verb_lvl=$ntf_lvl log "${colCya}[NOTI ]${colRst} $@" ; }
function ok() { verb_lvl=$ntf_lvl log "${colBlu}[SUCC ]${colRst} $@" ; }
function warn() { verb_lvl=$wrn_lvl log "${colYlw}[WARN ]${colRst} $@" ; }
function info() { verb_lvl=$inf_lvl log "${colBlk}[INFO ]${colRst} $@" ; }
function debug() { verb_lvl=$dbg_lvl log "${colGrn}[DEBUG]${colRst} $@" ; }
function error() { verb_lvl=$err_lvl log "${colRed}[ERROR]${colRst} $@" ; }
function crit() { verb_lvl=$crt_lvl log "${colPur}[FATAL]${colRst} $@" ; }
function log() {
if [ $verbosity -ge $verb_lvl ]; then
datestring=`date +"%Y-%m-%d %H:%M:%S"`
echo -e "$datestring $@"
fi
}
function fnCheckWarn() {
exitCode=$1
shift
if [ $exitCode -eq 0 ]; then
ok $@ succeded with exit code $exitCode
else
warn $@ failed with exit code $exitCode. The script will continue.
fi
# return the same code so other checks can follow this one inside the script
return $exitCode
}
function fnCheckExit() {
exitCode=$1
shift
if [ $exitCode -eq 0 ]; then
ok $@ succeded with exit code $exitCode
else
error $@ failed with exit code $exitCode. The script will exit.
exit $exitCode
fi
-
[2 단계] 작업 경로 및 필요한 라이브러리 경로를 설정
-
pid : 수행 쉘 작업 번호
-
presentYmd : 현재 시각
-
contextPath : 현재 작업 경로 설정
-
*Path : 로그/입력/출력/이미지/임시 경로를 설정하고 해당 디렉터리 생성
-
libPath, mapPath : GrADS 시각화를 위한 라이브러리 및 지도 경로 설정
-
logPathName : 로그 파일명 설정
-
#===============================================
# Config
#===============================================
pid=$(echo $$)
presentYmd=$(date +"%Y%m%d")
# echo "pid : " $pid
# echo "presentTime : " $presentTime
contextPath=$(pwd)
logPath=$contextPath/LOG
inpPath=$contextPath/INPUT
outPath=$contextPath/OUTPUT
imgPath=$contextPath/IMG
tmpPath=$contextPath/TMP
if [ ! -d $logPath ]; then mkdir -p $logPath; fi
if [ ! -d $inpPath ]; then mkdir -p $inpPath; fi
if [ ! -d $outPath ]; then mkdir -p $outPath; fi
if [ ! -d $imgPath ]; then mkdir -p $imgPath; fi
if [ ! -d $tmpPath ]; then mkdir -p $tmpPath; fi
libPath=/usr/local/grads-2.1.1.b0/config/lib
mapPath=/usr/local/grads-2.1.1.b0/config/map
logPathName=$logPath/Run_${presentYmd}.log
-
[3 단계] 텍스트 (CSV) 파일을 소프트웨어에 입력하기 용이한 형태로 변환
-
해당 CSV 형식에서 ,를 1칸 공백으로 변환
-
#================================================
Data Preprocessing
#================================================
info "======================== [START] Run Shell ======================================"
cat $inpPath/sst.txt | sed -e "s/,/ /g" > $inpPath/sstL1.txt
-
[4단계] 정적 소스 코드에 대한 Template를 생성
-
makeGridToBin.f90 : 위/경도 자료를 내삽하기 위한 1 km 해상도 격자 생성
-
grid.ctl : 위/경도 자료를 내삽하기 위한 Ctl 파일로서 XDEF, YDEF에서 해상도 설정 가능 (현재 0.3으로 30 km 의미)
-
makeTextToBin.f90 : 앞서 위/경도 자료 (CSV 파일 형식)을 읽고 바이너리 형식으로 출력
-
tmp.ctl : 위/경도 자료에 대한 Ctl 파일 설정
-
makePlotUsingGrADS.exec : 위/경도 및 격자에 대한 Ctl 파일을 읽고 oabin 내삽하여 시각화
-
해당 Template에서 %변수명의 경우 동적 변수를 의미
-
#================================================
# Template
#================================================
# set Grid
cat > makeGridToBin.f90 << EOF
!=======================================================
! sample program that produce a sample data for grads
!=======================================================
parameter (ni = 36000, nj = 18100, nk = 1, nt = 1)
real u(ni,nj,nk),v(ni,nj,nk), grid(ni,nj,nk),dum(ni,nj)
real(8) :: DX, DY
XMAX = 360
XMIN = 0
YMAX = 90
YMIN = -90
DX = (XMAX - XMIN) / (ni - 1)
DY = (YMAX - YMIN) / (nj - 1)
write(*,*) DX, DY
du = 100.0 / float(ni)
dv = 100.0 / float(nj)
open(10, file = 'OUTPUT/grid.bin', form = 'unformatted')
do m=1, nt
do k=1 ,nk
do j=1, nj
do i=1, ni
grid(i,j,k) = 0.0
enddo
enddo
enddo
! Print results
do k=1, nk
call load(grid, ni, nj, nk, k, dum)
write(10) dum
enddo
enddo
close(10)
stop
end
subroutine load(grid, ni, nj, nk, k, dum)
real,intent(in) :: grid(ni, nj, nk)
real,intent(out) :: dum(ni, nj)
do i=1,ni
do j=1,nj
dum(i,j) = grid(i,j,k)
end do
end do
return
end
EOF
# GrADS
cat > grid.ctl << EOF
DSET OUTPUT/grid.bin
TITLE Grid Data
UNDEF 0.10000E+16
XDEF 36000 linear 0 0.3
YDEF 18100 linear -90 0.3
ZDEF 1 levels 1000
TDEF 1 linear 00z01apr85 6hr
VARS 1
grid 0 99 **
ENDVARS
EOF
# set Val
# Fortran
cat > makeTextToBin.f90 << EOF
! implicit none
character(8) :: sta, end
integer(4) :: flag, lev, alt, year, month
real(4) :: lat, lon, val, time
open(8, file="$inpPath/sstL1.txt")
open(10, file="$tmpPath/tmp.bin", form="unformatted", access="stream")
! Header Info
read(8,*)
flag = 0
do
read(8, *, end=999) sta, lon, lat, val
if (sta /= "%dtYmd") cycle
if (val < 0) cycle
time = 0.0
lev = 1
flag = 1
write(10) sta, lat, lon, time, lev, flag
write(10) val
write(99, *) sta, lat, lon, time, lev, flag
write(99, *) val
enddo
999 lev = 0
flag = 0
lon = 0
lat = 0
write(10) end, lon, lat, time, lev, flag
write(99, *) end, lon, lat, time, lev, flag
stop
end
EOF
# GrADS
cat > tmp.ctl << EOF
DSET $tmpPath/tmp.bin
DTYPE station
STNMAP tmp.map
UNDEF 999.00
TDEF 1 linear apr2003 1mo
VARS 1
setVal 0 99 **
ENDVARS
EOF
cat > makePlotUsingGrADS.exec << EOF
reinit
${libPath}/xopen.gs tmp.ctl
${libPath}/xopen.gs grid.ctl
set display color white
set mpdset ${mapPath}/worldmap
set parea 0 11.0 1.5 8.0
set xlopts 1 6 0.18
set ylopts 1 6 0.18
set lat 28 40
set lon 120 136
set xlint 4
set ylint 4
set font 0
set grads off
set grid off
set gxout shaded
set csmooth on
${libPath}/color.gs 0 30 -div 100 -kind rainbow
* d oacres(grid.2, setVal.1)
d oabin(grid.2, setVal.1)
set gxout contour
set clopts 1 6 0.125
set cint 5
* d oacres(grid.2, setVal.1)
d oabin(grid.2, setVal.1)
${libPath}/xcbar.gs 1.5 9.5 0.4 0.65 -fwidth 0.18 -fheight 0.18 -edge circle -fstep 10 -line off
draw title %dtBdY
set string 1 tc
set strsiz 0.18 0.18
draw string 5.5 1.05 Sea Surface Temperature [C]
${mapPath}/basemap.gs L 0 1 M
* gxprint ${imgPath}/%imgPathName.png
${libPath}/save.gs ${imgPath}/%imgPathName -background white
!convert -trim -density 600 -rotate 90 ${imgPath}/%imgPathName.eps ${imgPath}/%imgPathName.png
!rm -f ${imgPath}/%imgPathName.eps
quit
EOF
-
[5단계] 동적 변수에 대한 변경 그리고 Fortran을 컴파일/실행하여 메모리상에 저장하고 가시화를 위한 초기 설정
-
1 km Grid 해상도가 없을 경우 주석을 해제하여 별도로 수행 (2.5 GB 용량 소모)
-
info "[CREATE] 1 km Grid"
# gfortran -mcmodel=large makeGridToBin.f90
# ./a.out
# stnmap -i grid.ctl
-
seq를 통해 기준 날짜 (2019-01-01)를 기준으로 일별로 생성하고 dtDateList 변수 설정
-
해당 변수를 통해 dtYmd, dtBdY, imgPathName 동적 변수를 설정
-
cat 및 sed 명령어를 통해 동적 변수를 치환하여 임시 소스 코드 (tmp.f90) 생성
-
gfortran를 통해 컴파일 및 실행하여 가시화를 위한 초기 설정
#===============================================
# Run
#===============================================
info "[CREATE] 1 km Grid"
# gfortran -mcmodel=large makeGridToBin.f90
# ./a.out
# stnmap -i grid.ctl
# setDate="2019-01-01"
setDate="2019-01-16"
dtDateList=$(seq 0 1 30 | xargs -I {} date -d "${setDate} {} days" +"%Y-%m-%d")
# dtDateList=$(seq 0 1 0 | xargs -I {} date -d "${setDate} {} days" +"%Y-%m-%d")
for getDate in $dtDateList; do
dtYmd=$(date -d "${getDate}" +"%Y%m%d")
dtBdY=$(date -d "${getDate}" +"%B %d, %Y")
imgPathName=Image_${dtYmd}
# imgPathName=Print_Image_${dtYmd}
debug ">>>>> [CHECK] getDate : $getDate <<<<<"
# Fortran
debug "[START] Run Fortran"
cat makeTextToBin.f90 \
| sed -e "s/%dtYmd/${dtYmd}/g" \
> $tmpPath/tmp.f90
gfortran $tmpPath/tmp.f90
fnCheckWarn "$?"
./a.out
fnCheckWarn "$?"
debug "[END] Run Fortran"
# GrADS
debug "[START] Run GrADS"
stnmap -i tmp.ctl > $logPathName 2>&1
cat makePlotUsingGrADS.exec \
| sed -e "s/%dtBdY/${dtBdY}/g" \
-e "s/%imgPathName/${imgPathName}/g" \
> $tmpPath/tmp.exec
grads -blc "exec $tmpPath/tmp.exec" > $logPathName 2>&1
fnCheckWarn "$?"
debug "[END] Run GrADS"
done
info "======================== [END] Run Shell ======================================"
-
[6 단계] ctl에 따라 영상 장면 표출하여 이미지 형식으로 저장합니다. 이 과정에서 포스트 스크립트 (EPS) 형식에서 PNG로 변환
-
GrADS에서도 cat 및 sed 명령어를 통해 동적 변수를 치환하여 임시 소스 코드 (tmp.exec) 생성
-
grads -blc를 통해 백그라운드로 실행하여 이미지를 생성한다.
-
[전체]
-
RunShell.sh
#!/bin/bash
# [Run Shell]
# bash RunShell.sh
# bash RunShell.sh > LOG/Run_$(date +"%Y%m%d").log
#================================================
# Function
#===============================================
source ~/.DefaultCommon.sh
#------------------
# Log Level Print
#------------------
# silent ""
# notify ""
# ok ""
# warn ""
# info ""
# debug ""
# error ""
# crit ""
#------------------
# Exit Code Check
#------------------
# fnCheckWarn "$?"
# fnCheckExit "$?"
#===============================================
# Config
#===============================================
pid=$(echo $$)
presentYmd=$(date +"%Y%m%d")
# echo "pid : " $pid
# echo "presentTime : " $presentTime
contextPath=$(pwd)
logPath=$contextPath/LOG
inpPath=$contextPath/INPUT
outPath=$contextPath/OUTPUT
imgPath=$contextPath/IMG
tmpPath=$contextPath/TMP
if [ ! -d $logPath ]; then mkdir -p $logPath; fi
if [ ! -d $inpPath ]; then mkdir -p $inpPath; fi
if [ ! -d $outPath ]; then mkdir -p $outPath; fi
if [ ! -d $imgPath ]; then mkdir -p $imgPath; fi
if [ ! -d $tmpPath ]; then mkdir -p $tmpPath; fi
libPath=/usr/local/grads-2.1.1.b0/config/lib
mapPath=/usr/local/grads-2.1.1.b0/config/map
logPathName=$logPath/Run_${presentYmd}.log
#================================================
# Data Preprocessing
#================================================
info "======================== [START] Run Shell ======================================"
cat $inpPath/sst.txt | sed -e "s/,/ /g" > $inpPath/sstL1.txt
#================================================
# Template
#================================================
# set Grid
cat > makeGridToBin.f90 << EOF
!=======================================================
! sample program that produce a sample data for grads
!=======================================================
parameter (ni = 36000, nj = 18100, nk = 1, nt = 1)
real u(ni,nj,nk),v(ni,nj,nk), grid(ni,nj,nk),dum(ni,nj)
real(8) :: DX, DY
XMAX = 360
XMIN = 0
YMAX = 90
YMIN = -90
DX = (XMAX - XMIN) / (ni - 1)
DY = (YMAX - YMIN) / (nj - 1)
write(*,*) DX, DY
du = 100.0 / float(ni)
dv = 100.0 / float(nj)
open(10, file = 'OUTPUT/grid.bin', form = 'unformatted')
do m=1, nt
do k=1 ,nk
do j=1, nj
do i=1, ni
grid(i,j,k) = 0.0
enddo
enddo
enddo
! Print results
do k=1, nk
call load(grid, ni, nj, nk, k, dum)
write(10) dum
enddo
enddo
close(10)
stop
end
subroutine load(grid, ni, nj, nk, k, dum)
real,intent(in) :: grid(ni, nj, nk)
real,intent(out) :: dum(ni, nj)
do i=1,ni
do j=1,nj
dum(i,j) = grid(i,j,k)
end do
end do
return
end
EOF
# GrADS
cat > grid.ctl << EOF
DSET OUTPUT/grid.bin
TITLE Grid Data
UNDEF 0.10000E+16
XDEF 36000 linear 0 0.3
YDEF 18100 linear -90 0.3
ZDEF 1 levels 1000
TDEF 1 linear 00z01apr85 6hr
VARS 1
grid 0 99 **
ENDVARS
EOF
# set Val
# Fortran
cat > makeTextToBin.f90 << EOF
! implicit none
character(8) :: sta, end
integer(4) :: flag, lev, alt, year, month
real(4) :: lat, lon, val, time
open(8, file="$inpPath/sstL1.txt")
open(10, file="$tmpPath/tmp.bin", form="unformatted", access="stream")
! Header Info
read(8,*)
flag = 0
do
read(8, *, end=999) sta, lon, lat, val
if (sta /= "%dtYmd") cycle
if (val < 0) cycle
time = 0.0
lev = 1
flag = 1
write(10) sta, lat, lon, time, lev, flag
write(10) val
write(99, *) sta, lat, lon, time, lev, flag
write(99, *) val
enddo
999 lev = 0
flag = 0
lon = 0
lat = 0
write(10) end, lon, lat, time, lev, flag
write(99, *) end, lon, lat, time, lev, flag
stop
end
EOF
# GrADS
cat > tmp.ctl << EOF
DSET $tmpPath/tmp.bin
DTYPE station
STNMAP tmp.map
UNDEF 999.00
TDEF 1 linear apr2003 1mo
VARS 1
setVal 0 99 **
ENDVARS
EOF
cat > makePlotUsingGrADS.exec << EOF
reinit
${libPath}/xopen.gs tmp.ctl
${libPath}/xopen.gs grid.ctl
set display color white
set mpdset ${mapPath}/worldmap
set parea 0 11.0 1.5 8.0
set xlopts 1 6 0.18
set ylopts 1 6 0.18
set lat 28 40
set lon 120 136
set xlint 4
set ylint 4
set font 0
set grads off
set grid off
set gxout shaded
set csmooth on
${libPath}/color.gs 0 30 -div 100 -kind rainbow
* d oacres(grid.2, setVal.1)
d oabin(grid.2, setVal.1)
set gxout contour
set clopts 1 6 0.125
set cint 5
* d oacres(grid.2, setVal.1)
d oabin(grid.2, setVal.1)
${libPath}/xcbar.gs 1.5 9.5 0.4 0.65 -fwidth 0.18 -fheight 0.18 -edge circle -fstep 10 -line off
draw title %dtBdY
set string 1 tc
set strsiz 0.18 0.18
draw string 5.5 1.05 Sea Surface Temperature [C]
${mapPath}/basemap.gs L 0 1 M
* gxprint ${imgPath}/%imgPathName.png
${libPath}/save.gs ${imgPath}/%imgPathName -background white
!convert -trim -density 600 -rotate 90 ${imgPath}/%imgPathName.eps ${imgPath}/%imgPathName.png
!rm -f ${imgPath}/%imgPathName.eps
quit
EOF
#===============================================
# Run
#===============================================
info "[CREATE] 1 km Grid"
# gfortran -mcmodel=large makeGridToBin.f90
# ./a.out
# stnmap -i grid.ctl
setDate="2019-01-01"
# setDate="2019-01-16"
dtDateList=$(seq 0 1 30 | xargs -I {} date -d "${setDate} {} days" +"%Y-%m-%d")
# dtDateList=$(seq 0 1 0 | xargs -I {} date -d "${setDate} {} days" +"%Y-%m-%d")
for getDate in $dtDateList; do
dtYmd=$(date -d "${getDate}" +"%Y%m%d")
dtBdY=$(date -d "${getDate}" +"%B %d, %Y")
imgPathName=Image_${dtYmd}
# imgPathName=Print_Image_${dtYmd}
debug ">>>>> [CHECK] getDate : $getDate <<<<<"
# Fortran
debug "[START] Run Fortran"
cat makeTextToBin.f90 \
| sed -e "s/%dtYmd/${dtYmd}/g" \
> $tmpPath/tmp.f90
gfortran $tmpPath/tmp.f90
fnCheckWarn "$?"
./a.out
fnCheckWarn "$?"
debug "[END] Run Fortran"
# GrADS
debug "[START] Run GrADS"
stnmap -i tmp.ctl > $logPathName 2>&1
cat makePlotUsingGrADS.exec \
| sed -e "s/%dtBdY/${dtBdY}/g" \
-e "s/%imgPathName/${imgPathName}/g" \
> $tmpPath/tmp.exec
grads -blc "exec $tmpPath/tmp.exec" > $logPathName 2>&1
fnCheckWarn "$?"
debug "[END] Run GrADS"
done
info "======================== [END] Run Shell ======================================"
fnCheckExit "$?"
참고 문헌
[논문]
- 없음
[보고서]
- 없음
[URL]
- 없음
문의사항
[기상학/프로그래밍 언어]
- sangho.lee.1990@gmail.com
[해양학/천문학/빅데이터]
- saimang0804@gmail.com
본 블로그는 파트너스 활동을 통해 일정액의 수수료를 제공받을 수 있음
'프로그래밍 언어 > GrADS' 카테고리의 다른 글
[GrADS] 그라즈 텍스트 (CSV) 형식인 ECMWF 해수면 온도 자료를 이용한 단번에 자료 처리 (Text) 및 시각화 (0) | 2020.07.05 |
---|---|
[GrADS] 오프라인 리눅스 (Linux) 환경에서 그라즈 (GrADS) 설치 및 공용 라이브러리 (Library) 설정 (0) | 2020.07.05 |
[GrADS] 그라즈 컬러 테이블 및 팔레트 소개 (0) | 2020.04.07 |
[GrADS, ShellScript] 그라즈 HDF 형식인 Terra/MODIS 및 Aqua/MODIS 자료를 이용한 에어로졸 광학두께 가시화 (0) | 2019.09.22 |
[GrADS, ShellScript] 그라즈 NetCDF 형식인 NOAA 월평균 해수면 온도 자료를 이용한 가시화 (0) | 2019.09.07 |
최근댓글