프로그래밍 언어/R

[R] KLAPS 수치예측 모델 자료를 이용하여 내삽 방법 (Inverse Distance Weighting, Linear Interpolation)에 따른 전처리 및 가시화

shlee1990 2020. 1. 3. 01:37

 정보

  • 업무명     : KLAPS 수치예측 모델 자료를 이용하여 내삽 방법 (Inverse Distance Weighting, Linear Interpolation)에 따른 전처리 및 가시화

  • 작성자     : 이상호

  • 작성일     : 2020-01-03

  • 설   명      :

  • 수정이력 :

 

 내용

[개요]

  • 안녕하세요? 기상 연구 및 웹 개발을 담당하고 있는 해솔입니다.

  • 이전 포스팅에서 역거리 가중치 (Inverse Distance Weighting) 및 선형 내삽 (Linear Interpolation) 방법을 설명했습니다. 이 방법은 간단하나 단점이 있습니다. 즉 내삽의 정확성이 다소 부정확하는 것입니다.

  • 오늘 포스팅은 KLAPS 수치예측 모델 자료를 이용하여 내삽 방법 (Inverse Distance Weighting, Linear Interpolation)에 따른 전처리 및 가시화를 소개해 드리고자 합니다.

 

  • 추가로 최근에 사용되는 내삽 방법 (Multi level B-Spline Approximation, Kriging) 방법을 소개하오니 참고하시기 바랍니다.

 

[R] KLAPS 수치예측 모델 자료를 이용하여 내삽 방법 (Multi level B-Spline Approximation, Kriging)에 따른 전처리 및 가시화

정보 업무명 : KLAPS 수치예측 모델 자료를 이용하여 내삽 방법 (Multi level B-Spline Approximation, Kriging)에 따른 전처리 및 가시화 작성자 : 이상호 작성일 : 2020-04-13 설 명 : 수정이력 : 내용 [개요]..

shlee1990.tistory.com

 

[특징]

  • KLAPS 수치예측 모델 자료 및 내삽 방법 (IDW, Linear Interpolation)를 이해하기 위해서 가시화가 요구되며 이 프로그램은 이러한 목적을 달성하기 위한 소프트웨어

 

[기능]

  • KLAPS 수치예측 모델 자료를 이용한 전처리 및 가시화

  • 역거리 가중치 (Inverse Distance Weighted, IDW)를 통해 전처리 및 가시화

  • 선형 내삽 (Linear Interpolation)을 통해 전처리 및 가시화

 

 

[활용 자료]

  • 자료명 : 초단기예보모델 (KLAPS)

  • 자료 종류 : 1100 hPa에서 지표면 온도

  • 영역 : 한반도

  • 확장자 : NetCDF

  • 기간 : 2019년 07월 03일 09시 00분 (KST)

  • 자료 설명 : 한반도 영역을 대상으로 3차원 예측자료를 생산하며 주로 한반도 영역의 3차원 분석/예측에 이용

 

[자료 처리 방안 및 활용 분석 기법]

  • 없음

 

[사용법]

  • 입력 자료를 동일 디렉터리 위치

  • 소스 코드를 실행
    (Rscript Visualization_and_Preprocessing_According_to_Interpolation_Method_using_KLAPS_
    numerical_Prediction_Model_Data
    )

  • 가시화 결과를 확인

 

[사용 OS]

  • Windows10

 

[사용 언어]

  • R v3.6.2

  • R Studio v1.2.5033

 

 소스 코드

[명세]

  • 전역 설정

    • 최대 10 자리 설정

    • 메모리 설정

# Set Option
options(digits = 10)
memory.limit(size = 9999999999999)

 

  • 라이브러리 읽기

# Library Load
library(RNetCDF)
library(tidyverse)
library(lubridate)
library(data.table)
library(colorRamps)
library(lubridate)
library(extrafont)
library(ggrepel)
library(scales)
library(sf)
library(gstat)
library(sp)
library(metR)
library(akima)
library(stringr)

 

  • 위/경도 파일 읽기

# File Geo Read
dfGeo = data.table::fread("INPUT/klaps_reanal_lation.txt", sep = "\t", header = FALSE)
colnames(dfGeo) = c("lon", "lat")

dplyr::tbl_df(dfGeo)

 

 

  • NetCDF 파일 검색

# File NetCDF Read
sInputFileDirName = "INPUT/*.nc"
sFileDirName = Sys.glob(sInputFileDirName)

length(sFileDirName)
sFileDirName

 

 

  • NetCDF 파일 열기

# NetCDF File Open
ncFile = open.nc(sFileDirName[iCount])

 

 

  • 출력/그림 파일명 설정

# Split File Name
sFileDirNameSplit = unlist(str_split(string = sFileDirName[iCount], pattern = "_|/|\\."))

# Get Date Time 
dtDateTimeUtc = lubridate::ymd_hm(sFileDirNameSplit[5])

# Convert UTC to KST
dtDateTimeKst = with_tz(dtDateTimeUtc, tzone = "Asia/Seoul")
sDateTimeKst = format(dtDateTimeKst, "%Y%m%d%H%M")

# Set Output File Name
sOutputFileDirName = paste0("OUTPUT/", sFileDirNameSplit[2], "_", sFileDirNameSplit[4], "_", sDateTimeKst, ".csv")

# Set Figure File Name
sFigureType = "Ori"
sFigureFileDirName = paste0("FIG/", sFileDirNameSplit[2], "_", sFileDirNameSplit[4], "_", sFigureType, "_", sDateTimeKst, ".png")

 

 

  • NetCDF 파일 읽기

# NetCDF File Read
ncData = read.nc(ncFile)

# print(ncData)

 

netcdf klps_lc05_anal_201907030000 {
dimensions:
	record = UNLIMITED ; // (1 currently)
	n_valtimes = 1 ;
	data_variables = 46 ;
	namelen = 132 ;
	charsPerLevel = 10 ;
	x = 235 ;
	y = 283 ;
	levels_1 = 1 ;
	levels_2 = 2 ;
	levels_3 = 3 ;
	levels_22 = 22 ;
	levels_23 = 23 ;
variables:
	float gh(record, levels_22, y, x) ;
		gh:long_name = "Geopotential height" ;
		gh:units = "m" ;
		gh:udunits = "meters" ;
		gh:uiname = "geoPotHt" ;
		gh:valid_range = 0.f, 20000.f ;
		gh:_FillValue = -99999.f ;
		gh:_n3D = 22 ;
		gh:levels = "MB 1100-50 by 50" ;
	char ghLevels(levels_22, charsPerLevel) ;
	char ghInventory(n_valtimes, levels_22) ;
	float rh(record, levels_23, y, x) ;
		rh:long_name = "Relative Humidity" ;
		rh:units = "%" ;
		rh:udunits = "percent" ;
		rh:uiname = "rh" ;
		rh:valid_range = 0.f, 100.f ;
		rh:_FillValue = -99999.f ;
		rh:_n3D = 23 ;
		rh:levels = "SFC  MB 1100-50 by 50" ;
	char rhLevels(levels_23, charsPerLevel) ;
	char rhInventory(n_valtimes, levels_23) ;
	float t(record, levels_23, y, x) ;
		t:long_name = "Temperature" ;
		t:units = "K" ;
		t:udunits = "degree_Kelvin" ;
		t:uiname = "T" ;
		t:valid_range = 180.f, 330.f ;
		t:_FillValue = -99999.f ;
		t:_n3D = 23 ;
		t:levels = "SFC  MB 1100-50 by 50" ;
	char tLevels(levels_23, charsPerLevel) ;
	char tInventory(n_valtimes, levels_23) ;
	float uw(record, levels_23, y, x) ;
		uw:long_name = "u wind component" ;
		uw:units = "m/s" ;
		uw:udunits = "meter/sec" ;
		uw:uiname = "uWind" ;
		uw:valid_range = -150.f, 150.f ;
		uw:_FillValue = -99999.f ;
		uw:_n3D = 23 ;
		uw:levels = "SFC  MB 1100-50 by 50" ;
	char uwLevels(levels_23, charsPerLevel) ;
	char uwInventory(n_valtimes, levels_23) ;
	float vw(record, levels_23, y, x) ;
		vw:long_name = "v wind component" ;
		vw:units = "m/s" ;
		vw:udunits = "meter/sec" ;
		vw:uiname = "vWind" ;
		vw:valid_range = -150.f, 150.f ;
		vw:_FillValue = -99999.f ;
		vw:_n3D = 23 ;
		vw:levels = "SFC  MB 1100-50 by 50" ;
	char vwLevels(levels_23, charsPerLevel) ;
	char vwInventory(n_valtimes, levels_23) ;
	float pvv(record, levels_23, y, x) ;
		pvv:long_name = "Pressure vertical velocity" ;
		pvv:units = "Pa/s" ;
		pvv:udunits = "pascal/second" ;
		pvv:uiname = "Pvv" ;
		pvv:valid_range = -2.5f, 2.5f ;
		pvv:_FillValue = -99999.f ;
		pvv:_n3D = 23 ;
		pvv:levels = "SFC  MB 1100-50 by 50" ;
	char pvvLevels(levels_23, charsPerLevel) ;
	char pvvInventory(n_valtimes, levels_23) ;
	float sh(record, levels_22, y, x) ;
		sh:long_name = "specific humidity" ;
		sh:units = "kg/kg" ;
		sh:udunits = "" ;
		sh:uiname = "sh" ;
		sh:valid_range = 0.f, 0.1f ;
		sh:_FillValue = -99999.f ;
		sh:_n3D = 22 ;
		sh:levels = "MB 1100-50 by 50" ;
	char shLevels(levels_22, charsPerLevel) ;
	char shInventory(n_valtimes, levels_22) ;
	float rr(record, levels_22, y, x) ;
		rr:long_name = "LAPS radar reflectivity" ;
		rr:units = "dBZ" ;
		rr:udunits = "" ;
		rr:uiname = "LapsRRef" ;
		rr:valid_range = -20.f, 80.f ;
		rr:_FillValue = -99999.f ;
		rr:_n3D = 22 ;
		rr:levels = "MB 1100-50 by 50" ;
	char rrLevels(levels_22, charsPerLevel) ;
	char rrInventory(n_valtimes, levels_22) ;
	float ptyp(record, levels_22, y, x) ;
		ptyp:long_name = "precipitation type" ;
		ptyp:units = "none" ;
		ptyp:udunits = "" ;
		ptyp:uiname = "PrecipType" ;
		ptyp:valid_range = 0.f, 20.f ;
		ptyp:_FillValue = -99999.f ;
		ptyp:_n3D = 22 ;
		ptyp:levels = "MB 1100-50 by 50" ;
	char ptypLevels(levels_22, charsPerLevel) ;
	char ptypInventory(n_valtimes, levels_22) ;
	float ctyp(record, levels_22, y, x) ;
		ctyp:long_name = "cloud type" ;
		ctyp:units = "none" ;
		ctyp:udunits = "" ;
		ctyp:uiname = "CldType" ;
		ctyp:valid_range = 0.f, 20.f ;
		ctyp:_FillValue = -99999.f ;
		ctyp:_n3D = 22 ;
		ctyp:levels = "MB 1100-50 by 50" ;
	char ctypLevels(levels_22, charsPerLevel) ;
	char ctypInventory(n_valtimes, levels_22) ;
	float ccpc(record, levels_22, y, x) ;
		ccpc:long_name = "fractional cloud cover pressure coord" ;
		ccpc:units = "fractional" ;
		ccpc:udunits = "" ;
		ccpc:uiname = "FracCldCvr" ;
		ccpc:valid_range = 0.f, 100.f ;
		ccpc:_FillValue = -99999.f ;
		ccpc:_n3D = 22 ;
		ccpc:levels = "MB 1100-50 by 50" ;
	char ccpcLevels(levels_22, charsPerLevel) ;
	char ccpcInventory(n_valtimes, levels_22) ;
	float cw(record, levels_22, y, x) ;
		cw:long_name = "cloud liquid water" ;
		cw:units = "grams/meter**3" ;
		cw:udunits = "kilogram/meters3" ;
		cw:uiname = "CldH20" ;
		cw:valid_range = 0.f, 100.f ;
		cw:_FillValue = -99999.f ;
		cw:_n3D = 22 ;
		cw:levels = "MB 1100-50 by 50" ;
	char cwLevels(levels_22, charsPerLevel) ;
	char cwInventory(n_valtimes, levels_22) ;
	float cice(record, levels_22, y, x) ;
		cice:long_name = "cloud ice" ;
		cice:units = "grams/meter**3" ;
		cice:udunits = "kilogram/meters3" ;
		cice:uiname = "CldIce" ;
		cice:valid_range = 0.f, 100.f ;
		cice:_FillValue = -99999.f ;
		cice:_n3D = 22 ;
		cice:levels = "MB 1100-50 by 50" ;
	char ciceLevels(levels_22, charsPerLevel) ;
	char ciceInventory(n_valtimes, levels_22) ;
	float hyc(record, levels_22, y, x) ;
		hyc:long_name = "hydrometeor concentration" ;
		hyc:units = "grams/meter**3" ;
		hyc:udunits = "kilogram/meters3" ;
		hyc:uiname = "HmConc" ;
		hyc:valid_range = 0.f, 100.f ;
		hyc:_FillValue = -99999.f ;
		hyc:_n3D = 22 ;
		hyc:levels = "MB 1100-50 by 50" ;
	char hycLevels(levels_22, charsPerLevel) ;
	char hycInventory(n_valtimes, levels_22) ;
	float p(record, levels_2, y, x) ;
		p:long_name = "pressure" ;
		p:units = "Pa" ;
		p:udunits = "pascal" ;
		p:uiname = "atmP" ;
		p:valid_range = 0.f, 110000.f ;
		p:_FillValue = -99999.f ;
		p:_n3D = 1 ;
		p:levels = "SFC  FH 1500" ;
	char pLevels(levels_2, charsPerLevel) ;
	char pInventory(n_valtimes, levels_2) ;
	float mslp(record, levels_1, y, x) ;
		mslp:long_name = "Mean Sea Level Pressure" ;
		mslp:units = "Pa" ;
		mslp:udunits = "pascal" ;
		mslp:uiname = "MSL" ;
		mslp:valid_range = 80000.f, 110000.f ;
		mslp:_FillValue = -99999.f ;
		mslp:_n3D = 0 ;
		mslp:levels = "SFC" ;
	char mslpLevels(levels_1, charsPerLevel) ;
	char mslpInventory(n_valtimes, levels_1) ;
	float dpt(record, levels_1, y, x) ;
		dpt:long_name = "surface dewpoint temperature" ;
		dpt:units = "K" ;
		dpt:udunits = "degree_Kelvin" ;
		dpt:uiname = "Td" ;
		dpt:valid_range = 180.f, 330.f ;
		dpt:_FillValue = -99999.f ;
		dpt:_n3D = 0 ;
		dpt:levels = "SFC" ;
	char dptLevels(levels_1, charsPerLevel) ;
	char dptInventory(n_valtimes, levels_1) ;
	float pot(record, levels_1, y, x) ;
		pot:long_name = "potential temperature" ;
		pot:units = "K" ;
		pot:udunits = "degree_Kelvin" ;
		pot:uiname = "Tp" ;
		pot:valid_range = 180.f, 330.f ;
		pot:_FillValue = -99999.f ;
		pot:_n3D = 0 ;
		pot:levels = "SFC" ;
	char potLevels(levels_1, charsPerLevel) ;
	char potInventory(n_valtimes, levels_1) ;
	float cc(record, levels_2, y, x) ;
		cc:long_name = "cloud ceiling" ;
		cc:units = "K" ;
		cc:udunits = "degree_Kelvin" ;
		cc:uiname = "CldCeil" ;
		cc:valid_range = 0.f, 20000.f ;
		cc:_FillValue = -99999.f ;
		cc:_n3D = 0 ;
		cc:levels = "SFC  MSL" ;
	char ccLevels(levels_2, charsPerLevel) ;
	char ccInventory(n_valtimes, levels_2) ;
	float tadv(record, levels_1, y, x) ;
		tadv:long_name = "temperature advection" ;
		tadv:units = "K/s" ;
		tadv:udunits = "Kelvin/second" ;
		tadv:uiname = "Tadv" ;
		tadv:valid_range = -0.02f, 0.02f ;
		tadv:_FillValue = -99999.f ;
		tadv:_n3D = 0 ;
		tadv:levels = "SFC" ;
	char tadvLevels(levels_1, charsPerLevel) ;
	char tadvInventory(n_valtimes, levels_1) ;
	float ept(record, levels_1, y, x) ;
		ept:long_name = "equivalent potential temperature" ;
		ept:units = "K" ;
		ept:udunits = "degree_Kelvin" ;
		ept:uiname = "EqPot" ;
		ept:valid_range = 180.f, 330.f ;
		ept:_FillValue = -99999.f ;
		ept:_n3D = 0 ;
		ept:levels = "SFC" ;
	char eptLevels(levels_1, charsPerLevel) ;
	char eptInventory(n_valtimes, levels_1) ;
	float ilw(record, levels_1, y, x) ;
		ilw:long_name = "integrated liquid water" ;
		ilw:units = "grams/meter**3" ;
		ilw:udunits = "kilogram/meters3" ;
		ilw:uiname = "IntLiqH20" ;
		ilw:valid_range = 0.f, 2000.f ;
		ilw:_FillValue = -99999.f ;
		ilw:_n3D = 0 ;
		ilw:levels = "SFC" ;
	char ilwLevels(levels_1, charsPerLevel) ;
	char ilwInventory(n_valtimes, levels_1) ;
	float mcon(record, levels_1, y, x) ;
		mcon:long_name = "moisture convergence" ;
		mcon:units = "grams/meters**3" ;
		mcon:udunits = "kilogram/meters3" ;
		mcon:uiname = "moistConv" ;
		mcon:valid_range = -0.01f, 0.01f ;
		mcon:_FillValue = -99999.f ;
		mcon:_n3D = 0 ;
		mcon:levels = "SFC" ;
	char mconLevels(levels_1, charsPerLevel) ;
	char mconInventory(n_valtimes, levels_1) ;
	float pta(record, levels_1, y, x) ;
		pta:long_name = "potential temperature advection" ;
		pta:units = "K/s" ;
		pta:udunits = "Kelvin/second" ;
		pta:uiname = "PotTadv" ;
		pta:valid_range = -0.02f, 0.02f ;
		pta:_FillValue = -99999.f ;
		pta:_n3D = 0 ;
		pta:levels = "SFC" ;
	char ptaLevels(levels_1, charsPerLevel) ;
	char ptaInventory(n_valtimes, levels_1) ;
	float sli(record, levels_1, y, x) ;
		sli:long_name = "lifted index" ;
		sli:units = "K" ;
		sli:udunits = "degree_Kelvin" ;
		sli:uiname = "LftInd" ;
		sli:valid_range = -20.f, 20.f ;
		sli:_FillValue = -99999.f ;
		sli:_n3D = 0 ;
		sli:levels = "SFC" ;
	char sliLevels(levels_1, charsPerLevel) ;
	char sliInventory(n_valtimes, levels_1) ;
	float ki(record, levels_1, y, x) ;
		ki:long_name = "K index" ;
		ki:units = "K" ;
		ki:udunits = "degree_Kelvin" ;
		ki:uiname = "KInd" ;
		ki:valid_range = -20.f, 20.f ;
		ki:_FillValue = -99999.f ;
		ki:_n3D = 1 ;
		ki:levels = "EA" ;
	char kiLevels(levels_1, charsPerLevel) ;
	char kiInventory(n_valtimes, levels_1) ;
	float ttot(record, levels_1, y, x) ;
		ttot:long_name = "Total totals index" ;
		ttot:units = "K" ;
		ttot:udunits = "degree_Kelvin" ;
		ttot:uiname = "TotInd" ;
		ttot:valid_range = -20.f, 20.f ;
		ttot:_FillValue = -99999.f ;
		ttot:_n3D = 1 ;
		ttot:levels = "EA" ;
	char ttotLevels(levels_1, charsPerLevel) ;
	char ttotInventory(n_valtimes, levels_1) ;
	float shwlt(record, levels_1, y, x) ;
		shwlt:long_name = "Showalter  index" ;
		shwlt:units = "K" ;
		shwlt:udunits = "degree_Kelvin" ;
		shwlt:uiname = "TotInd" ;
		shwlt:valid_range = -20.f, 20.f ;
		shwlt:_FillValue = -99999.f ;
		shwlt:_n3D = 1 ;
		shwlt:levels = "850MB" ;
	char shwltLevels(levels_1, charsPerLevel) ;
	char shwltInventory(n_valtimes, levels_1) ;
	float hidx(record, levels_1, y, x) ;
		hidx:long_name = "Heat index" ;
		hidx:units = "K" ;
		hidx:udunits = "degree_Kelvin" ;
		hidx:uiname = "HeatInd" ;
		hidx:valid_range = 270.f, 330.f ;
		hidx:_FillValue = -99999.f ;
		hidx:_n3D = 0 ;
		hidx:levels = "SFC" ;
	char hidxLevels(levels_1, charsPerLevel) ;
	char hidxInventory(n_valtimes, levels_1) ;
	float cssi(record, levels_1, y, x) ;
		cssi:long_name = "colorado severe storm index" ;
		cssi:units = "none" ;
		cssi:udunits = "" ;
		cssi:uiname = "SevStInd" ;
		cssi:valid_range = -20000.f, 20000.f ;
		cssi:_FillValue = -99999.f ;
		cssi:_n3D = 0 ;
		cssi:levels = "SFC" ;
	char cssiLevels(levels_1, charsPerLevel) ;
	char cssiInventory(n_valtimes, levels_1) ;
	float pbe(record, levels_1, y, x) ;
		pbe:long_name = "positive buoyant energy" ;
		pbe:units = "J/kg" ;
		pbe:udunits = "joule/Kilogram" ;
		pbe:uiname = "PosBuoyE" ;
		pbe:valid_range = 0.f, 6000.f ;
		pbe:_FillValue = -99999.f ;
		pbe:_n3D = 0 ;
		pbe:levels = "SFC" ;
	char pbeLevels(levels_1, charsPerLevel) ;
	char pbeInventory(n_valtimes, levels_1) ;
	float nbe(record, levels_1, y, x) ;
		nbe:long_name = "negative buoyant energy" ;
		nbe:units = "J/kg" ;
		nbe:udunits = "joule/Kilogram" ;
		nbe:uiname = "NegBuoyE" ;
		nbe:valid_range = 0.f, 6000.f ;
		nbe:_FillValue = -99999.f ;
		nbe:_n3D = 0 ;
		nbe:levels = "SFC" ;
	char nbeLevels(levels_1, charsPerLevel) ;
	char nbeInventory(n_valtimes, levels_1) ;
	float vis(record, levels_1, y, x) ;
		vis:long_name = "visibility" ;
		vis:units = "m" ;
		vis:udunits = "meters" ;
		vis:uiname = "Vis" ;
		vis:_FillValue = -99999.f ;
		vis:valid_range = 0.f, 100000.f ;
		vis:_n3D = 0 ;
		vis:levels = "SFC" ;
	char visLevels(levels_1, charsPerLevel) ;
	char visInventory(n_valtimes, levels_1) ;
	float ccov(record, levels_1, y, x) ;
		ccov:long_name = "LAPS cloud cover" ;
		ccov:units = "%" ;
		ccov:udunits = "percent" ;
		ccov:uiname = "LapsCldCvr" ;
		ccov:valid_range = 0.f, 100.f ;
		ccov:_FillValue = -99999.f ;
		ccov:_n3D = 0 ;
		ccov:levels = "SFC" ;
	char ccovLevels(levels_1, charsPerLevel) ;
	char ccovInventory(n_valtimes, levels_1) ;
	float cb(record, levels_1, y, x) ;
		cb:long_name = "LAPS cloud base" ;
		cb:units = "m" ;
		cb:udunits = "meters" ;
		cb:uiname = "LapsCldBase" ;
		cb:valid_range = 0.f, 10000.f ;
		cb:_FillValue = -99999.f ;
		cb:_n3D = 0 ;
		cb:levels = "SFC" ;
	char cbLevels(levels_1, charsPerLevel) ;
	char cbInventory(n_valtimes, levels_1) ;
	float ctop(record, levels_1, y, x) ;
		ctop:long_name = "LAPS cloud top" ;
		ctop:units = "m" ;
		ctop:udunits = "meters" ;
		ctop:uiname = "LapsCldTop" ;
		ctop:valid_range = 0.f, 50000.f ;
		ctop:_FillValue = -99999.f ;
		ctop:_n3D = 0 ;
		ctop:levels = "SFC" ;
	char ctopLevels(levels_1, charsPerLevel) ;
	char ctopInventory(n_valtimes, levels_1) ;
	float mret(record, levels_1, y, x) ;
		mret:long_name = "maximum radar echo tops" ;
		mret:units = "m" ;
		mret:udunits = "meters" ;
		mret:uiname = "MaxRdrEcho" ;
		mret:valid_range = 0.f, 50000.f ;
		mret:_FillValue = -99999.f ;
		mret:_n3D = 0 ;
		mret:levels = "SFC" ;
	char mretLevels(levels_1, charsPerLevel) ;
	char mretInventory(n_valtimes, levels_1) ;
	float llr(record, levels_1, y, x) ;
		llr:long_name = "low level reflectivity" ;
		llr:units = "dBZ" ;
		llr:udunits = "" ;
		llr:uiname = "ReflectLL" ;
		llr:valid_range = -20.f, 80.f ;
		llr:_FillValue = -99999.f ;
		llr:_n3D = 0 ;
		llr:levels = "SFC" ;
	char llrLevels(levels_1, charsPerLevel) ;
	char llrInventory(n_valtimes, levels_1) ;
	float heli(record, levels_1, y, x) ;
		heli:long_name = "helicity" ;
		heli:units = "m2/s2" ;
		heli:udunits = "meter2/second2" ;
		heli:uiname = "hel" ;
		heli:valid_range = 0.f, 1000.f ;
		heli:_FillValue = -99999.f ;
		heli:_n3D = 0 ;
		heli:levels = "SFC" ;
	char heliLevels(levels_1, charsPerLevel) ;
	char heliInventory(n_valtimes, levels_1) ;
	float tpw(record, levels_1, y, x) ;
		tpw:long_name = "integrated total precipitable water" ;
		tpw:units = "m" ;
		tpw:udunits = "meters" ;
		tpw:uiname = "TotPrecipH20" ;
		tpw:valid_range = 0.f, 0.01f ;
		tpw:_FillValue = -99999.f ;
		tpw:_n3D = 0 ;
		tpw:levels = "SFC" ;
	char tpwLevels(levels_1, charsPerLevel) ;
	char tpwInventory(n_valtimes, levels_1) ;
	float s1hr(record, levels_1, y, x) ;
		s1hr:long_name = "LAPS 60 minute snow accum." ;
		s1hr:units = "m" ;
		s1hr:udunits = "meters" ;
		s1hr:uiname = "LapsSnow60" ;
		s1hr:valid_range = 0.f, 1.f ;
		s1hr:_FillValue = -99999.f ;
		s1hr:_n3D = 0 ;
		s1hr:levels = "SFC" ;
	char s1hrLevels(levels_1, charsPerLevel) ;
	char s1hrInventory(n_valtimes, levels_1) ;
	float stot(record, levels_1, y, x) ;
		stot:long_name = "storm total snow accumulation" ;
		stot:units = "m" ;
		stot:udunits = "meters" ;
		stot:uiname = "StmTotSnow" ;
		stot:valid_range = 0.f, 10.f ;
		stot:_FillValue = -99999.f ;
		stot:_n3D = 0 ;
		stot:levels = "SFC" ;
	char stotLevels(levels_1, charsPerLevel) ;
	char stotInventory(n_valtimes, levels_1) ;
	float pc(record, levels_1, y, x) ;
		pc:long_name = "LAPS 60 minute precip. accum." ;
		pc:units = "m" ;
		pc:udunits = "meters" ;
		pc:uiname = "LapsPrecip60" ;
		pc:valid_range = 0.f, 0.1f ;
		pc:_FillValue = -99999.f ;
		pc:_n3D = 0 ;
		pc:levels = "SFC" ;
	char pcLevels(levels_1, charsPerLevel) ;
	char pcInventory(n_valtimes, levels_1) ;
	float stpa(record, levels_1, y, x) ;
		stpa:long_name = "storm total precip. accum." ;
		stpa:units = "m" ;
		stpa:udunits = "meters" ;
		stpa:uiname = "StmTotPrecip" ;
		stpa:valid_range = 0.f, 2.f ;
		stpa:_FillValue = -99999.f ;
		stpa:_n3D = 0 ;
		stpa:levels = "SFC" ;
	char stpaLevels(levels_1, charsPerLevel) ;
	char stpaInventory(n_valtimes, levels_1) ;
	float spt(record, levels_1, y, x) ;
		spt:long_name = "LAPS precip type" ;
		spt:units = "none" ;
		spt:udunits = "" ;
		spt:uiname = "LapsPrecipTyp" ;
		spt:valid_range = 0.f, 20.f ;
		spt:_FillValue = -99999.f ;
		spt:_n3D = 0 ;
		spt:levels = "SFC" ;
	char sptLevels(levels_1, charsPerLevel) ;
	char sptInventory(n_valtimes, levels_1) ;
	float ptt(record, levels_1, y, x) ;
		ptt:long_name = "LAPS precip type - LL radar ref modified" ;
		ptt:units = "none" ;
		ptt:udunits = "" ;
		ptt:uiname = "LapsPrecipTypLL" ;
		ptt:valid_range = 0.f, 7.f ;
		ptt:_FillValue = -99999.f ;
		ptt:_n3D = 0 ;
		ptt:levels = "SFC" ;
	char pttLevels(levels_1, charsPerLevel) ;
	char pttInventory(n_valtimes, levels_1) ;
	float fd(record, levels_1, y, x) ;
		fd:long_name = "Fire Index" ;
		fd:units = "none" ;
		fd:udunits = "" ;
		fd:uiname = "FInd" ;
		fd:valid_range = 0.f, 20.f ;
		fd:_FillValue = -99999.f ;
		fd:_n3D = 0 ;
		fd:levels = "SFC" ;
	char fdLevels(levels_1, charsPerLevel) ;
	char fdInventory(n_valtimes, levels_1) ;
	float scp(record, levels_1, y, x) ;
		scp:long_name = "snow cover percentage" ;
		scp:units = "%" ;
		scp:udunits = "percent" ;
		scp:uiname = "SnCvrPer" ;
		scp:valid_range = 0.f, 100.f ;
		scp:_FillValue = -99999.f ;
		scp:_n3D = 0 ;
		scp:levels = "SFC" ;
	char scpLevels(levels_1, charsPerLevel) ;
	char scpInventory(n_valtimes, levels_1) ;
	float smc(record, levels_3, y, x) ;
		smc:long_name = "soil moisture" ;
		smc:units = "m/m" ;
		smc:udunits = "" ;
		smc:uiname = "soilM" ;
		smc:valid_range = 0.f, 1.f ;
		smc:_FillValue = -99999.f ;
		smc:_n3D = 0 ;
		smc:levels = "BLS 1 2 3" ;
	char smcLevels(levels_3, charsPerLevel) ;
	char smcInventory(n_valtimes, levels_3) ;
	int valtimeMINUSreftime(n_valtimes) ;
		valtimeMINUSreftime:units = "seconds" ;
	double valtime(record) ;
		valtime:long_name = "valid time" ;
		valtime:units = "seconds since (1970-1-1 00:00:00.0)" ;
	double reftime ;
		reftime:long_name = "reference time" ;
		reftime:units = "seconds since (1970-1-1 00:00:00.0)" ;
	char origin(namelen) ;
	char model(namelen) ;
	float staticTopo(y, x) ;
		staticTopo:units = "meters" ;
		staticTopo:long_name = "Topography" ;
		staticTopo:_FillValue = -99999.f ;
	float staticCoriolis(y, x) ;
		staticCoriolis:units = "/second" ;
		staticCoriolis:long_name = "Coriolis parameter" ;
		staticCoriolis:_FillValue = -99999.f ;
	float staticSpacing(y, x) ;
		staticSpacing:units = "meters" ;
		staticSpacing:long_name = "Grid spacing" ;
		staticSpacing:_FillValue = -99999.f ;

// global attributes:
		:cdlDate = "20020221" ;
		:depictorName = "klps@19022779" ;
		:projIndex = 3 ;
		:projName = "LAMBERT_CONFORMAL" ;
		:centralLat = 38.f ;
		:centralLon = 126.f ;
		:rotation = 30.f ;
		:xMin = -0.04383551f ;
		:xMax = 0.04585243f ;
		:yMax = -0.614959f ;
		:yMin = -0.7228721f ;
		:lat00 = 31.34451f ;
		:lon00 = 119.7993f ;
		:latNxNy = 44.28384f ;
		:lonNxNy = 133.6194f ;
		:dxKm = 5.13378f ;
		:dyKm = 5.125592f ;
		:latDxDy = 38.02223f ;
		:lonDxDy = 126.1543f ;
}

 

  • NetCDF 파일에서 1000 hPa의 지표면 온도 가져오기

# Get Variable
nTemp  = ncData[["t"]][ , , 1]

 

  • Data Frame 형태로 초기화

# Set Data Frame
dfData = data.frame(c(nTemp)) %>%
    dplyr::bind_cols(dfGeo) %>%
    dplyr::rename(
        nTemp = c.nTemp.
        , nLon = lon
        , nLat = lat
    )

# Print Data Frame
dplyr::tbl_df(dfData)

 

 

  • Data Frame를 통해 L1 전처리

    • 위도, 경도, 온도에 대한 최대값/최소값 설정

# L1 Processing Using Data Frame
dfDataL1 = dfData %>%
    dplyr::filter(
        dplyr::between(nLat, -90.0, 90.0)
        , dplyr::between(nLon, -180.0, 180.0)
        , dplyr::between(nTemp, 180.0, 330.0)
    )
    
# Print Data Frame
dplyr::tbl_df(dfDataL1)

 

 

  • L1 자료를 통해 출력

# Write Using L1 Data Frame 
data.table::fwrite(
    dfDataL1
    , file = sOutputFileDirName
    , sep = ","
    , append = FALSE
    , row.names = FALSE
    , col.names = TRUE
    , dateTimeAs = "write.csv"
    , na = NA 
    )

 

 

 

  • L1 자료를 통해 L2 전처리

    • 열 변수 변경 (nTemp → nVal)
# L2 Processing Using L1 Data Frame
dfDataL2 = dfDataL1 %>%
    dplyr::rename(nVal = nTemp)

 

  • 가시화를 위한 설정

    • 컬러바 설정

    • 폰트 설정

    • 대한민국/북한/일본 Shp 파일 설정

# Set Value for Visualization
cbMatlab =  colorRamps::matlab.like(11)
font = "Palatino Linotype"
mapKor = read_sf("INPUT/gadm36_KOR_shp/gadm36_KOR_1.shp")
mapPrk = read_sf("INPUT/gadm36_PRK_shp/gadm36_PRK_1.shp")
mapJpn = read_sf("INPUT/gadm36_JPN_shp/gadm36_JPN_1.shp")

 

 

  • L2 자료를 이용한 맵핑

    • 지표면 온도에 대한 점으로 맵핑

    • 대한민국/북한/일본 Shp

# Map Visualization Using ggplot2
ggplot() + 
    coord_fixed(ratio = 1.1) +
    theme_bw() +
    geom_point(data = dfDataL2, aes(x = nLon, y = nLat, colour = nVal), shape = 15) +
    scale_colour_gradientn(colours = cbMatlab, limits=c(285, 305), breaks = seq(285, 305, 5), na.value = cbMatlab[length(cbMatlab)]) +
    geom_sf(data = mapKor, color = "black", fill = NA) +
    geom_sf(data = mapPrk, color = "black", fill = NA) +
    geom_sf(data = mapJpn, color = "black", fill = NA) +
    metR::scale_x_longitude(expand = c(0, 0), breaks = seq(124, 132, 2), limits = c(124, 132)) +
    metR::scale_y_latitude(expand = c(0, 0), breaks = seq(32, 40, 1), limits = c(33, 39)) +
    labs(x = ""
         , y = ""
         , fill = ""
         , colour = ""
         , title  = ""
    ) +
    theme(
        plot.title = element_text(face = "bold", size = 18, color = "black")
        , axis.title.x = element_text(face = "bold", size = 18, colour = "black")
        , axis.title.y = element_text(face = "bold", size=18, colour = "black", angle = 90)
        , axis.text.x = element_text(face = "bold", size=18, colour = "black")
        , axis.text.y = element_text(face = "bold", size=18, colour = "black")
        , legend.position = c(1, 1.03)
        , legend.justification = c(1, 1)
        , legend.key = element_blank()
        , legend.text = element_text(size = 14, face = "bold")
        , legend.title = element_text(face = "bold", size = 14, colour = "black")
        , legend.background=element_blank()
        , text=element_text(family = font)
        , plot.margin = unit(c(0, 8, 0, 0), "mm")
    ) +
    ggsave(filename = sFigureFileDirName, width = 8, height = 10, dpi = 600)

 

그림. 2019년 07월 03일 09시 00분에 KLAPS 수치예측 모델 자료를 이용한 지표면 온도 가시화.

 

  • 역거리 가중치를 통해 L2 전처리

    • 내삽을 위한 위/경도 및 해상도 설정

    • 신규 격자 (spNewData)에 대해 "역거리 가중치 (IDW)" 공간 내삽 수행

  •  
#=================================================
#   Inverse Distance Weighted
#=================================================
sFigureType = "Idw"

# Min/Max Longitude of the Interpolation Area
xRange = as.numeric(c(124, 132))  

# Min/Max Latitude of the Interpolation Area
yRange = as.numeric(c(33, 39)) 

# Expand Points to Grid
spNewData = expand.grid(
    x = seq(from = xRange[1], to = xRange[2], by = 0.01)
    , y = seq(from = yRange[1], to = yRange[2], by = 0.01)
)

coordinates(spNewData) = ~ x + y
gridded(spNewData) = TRUE
# plot(spNewData)

# Apply IDW Model for the Data
spDataL1 = gstat::idw(
    formula = nTemp ~ 1
    , locations = spData
    , newdata = spNewData
    , nmax = 4
    )

# L2 Processing Using L1 Data Frame
dfDataL2 = spDataL1 %>%
    as.data.frame() %>%
    dplyr::rename(
        nLon = x
        , nLat = y
        , nVal = var1.pred
    )

 

  • 선형 내삽을 통해 L2 전처리

    • 내삽을 위한 위/경도 및 해상도 설정

    • 신규 격자 (nNewLon, nNewLat)에 대해 "선형 내삽" 수행

  •  
#=================================================
#   Linear Interpolation
#=================================================
sFigureType = "Interp"

# Min/Max Longitude of the Interpolation Area
xRange = as.numeric(c(124, 132))

# Min/Max Latitude of the Interpolation Area
yRange = as.numeric(c(33, 39))

nNewLon = seq(from = xRange[1], to = xRange[2], by = 0.01)
nNewLat = seq(from = yRange[1], to = yRange[2], by = 0.01)

dfTmp = akima::interp(
    dfData$nLon
    , dfData$nLat
    , dfData$nTemp
    , xo = nNewLon
    , yo = nNewLat
)

# Expand Points to Grid
spGeoData = expand.grid(nNewLon, nNewLat)

coordinates(spGeoData) = ~ x + y
gridded(spGeoData) = TRUE

# L2 Processing Using L1 Data Frame
dfDataL2 = data.frame(
    nLon = spGeoData$Var1
    , nLat = spGeoData$Var2
    , nVal = c(dfTmp$z)
)

dplyr::glimpse(dfDataL2)

 

  • 가시화를 위한 설정

    • 컬러바 설정

    • 폰트 설정

    • 대한민국/북한/일본 Shp 파일 설정

    • 그림 파일명 설정

# Set Value for Visualization
cbMatlab =  colorRamps::matlab.like(11)
font = "Palatino Linotype"
mapKor = read_sf("INPUT/gadm36_KOR_shp/gadm36_KOR_1.shp")
mapPrk = read_sf("INPUT/gadm36_PRK_shp/gadm36_PRK_1.shp")
mapJpn = read_sf("INPUT/gadm36_JPN_shp/gadm36_JPN_1.shp")

sFigureFileDirName = paste0("FIG/", sFileDirNameSplit[2], "_", sFileDirNameSplit[4], "_", sFigureType, "_", sDateTimeKst, ".png")

 

  • L2 자료를 이용한 맵핑

    • 지표면 온도에 대한 등치선으로 맵핑

    • 대한민국/북한/일본 Shp

# Map Visualization Using ggplot2
ggplot() + 
    coord_fixed(ratio = 1.1) +
    theme_bw() +
    geom_tile(data = dfDataL2, aes(x = nLon, y = nLat, fill = nVal)) +
    scale_fill_gradientn(colours = cbMatlab, limits=c(285, 305), breaks = seq(285, 305, 5), na.value = cbMatlab[length(cbMatlab)]) +
    geom_sf(data = mapKor, color = "black", fill = NA) +
    geom_sf(data = mapPrk, color = "black", fill = NA) +
    geom_sf(data = mapJpn, color = "black", fill = NA) +
    metR::scale_x_longitude(expand = c(0, 0), breaks = seq(124, 132, 2), limits = c(124, 132)) +
    metR::scale_y_latitude(expand = c(0, 0), breaks = seq(32, 40, 1), limits = c(33, 39)) +
    labs(x = ""
         , y = ""
         , fill = ""
         , colour = ""
         , title  = ""
    ) +
    theme(
        plot.title = element_text(face = "bold", size = 18, color = "black")
        , axis.title.x = element_text(face = "bold", size = 18, colour = "black")
        , axis.title.y = element_text(face = "bold", size=18, colour = "black", angle = 90)
        , axis.text.x = element_text(face = "bold", size=18, colour = "black")
        , axis.text.y = element_text(face = "bold", size=18, colour = "black")
        , legend.position = c(1, 1.03)
        , legend.justification = c(1, 1)
        , legend.key = element_blank()
        , legend.text = element_text(size = 14, face = "bold")
        , legend.title = element_text(face = "bold", size = 14, colour = "black")
        , legend.background=element_blank()
        , text=element_text(family = font)
        , plot.margin = unit(c(0, 8, 0, 0), "mm")
    ) +
    ggsave(filename = sFigureFileDirName, width = 8, height = 10, dpi = 600)

 

  • 역거리 가중치

그림. 2019년 07월 03일 09시 00분에 KLAPS 수치예측 모델 자료 및 역거리 가중치 공간 내삽을 이용한 지표면 온도 가시화.

 

  • 선형 내삽

그림. 2019년 07월 03일 09시 00분에 KLAPS 수치예측 모델 자료 및 선형 내삽을 이용한 지표면 온도 가시화.

 

[전체]

 

 참고 문헌

[논문]

  • 없음

[보고서]

  • 없음

[URL]

  • 없음

 

 문의사항

[기상학/프로그래밍 언어]

  • sangho.lee.1990@gmail.com

[해양학/천문학/빅데이터]

  • saimang0804@gmail.com