NetCDF4 데이터 가시화(1)

2 minute read

NetCDF4 데이터를 읽어서 다음과 같이 가시화해보겠다.

ts_uv_final

사용 데이터는 Hycom 재분석 자료이며, 관련 링크는 다음과 같다.

파일의 마지막에 ts3z라 적혀 있으면 수온 및 염분 데이터, uv3z는 유속 UV 데이터이다. 그리고 ssh는 수위이다.
우리가 가시화하고자 하는 데이터는 수온과 UV를 사용하므로 이 두가지를 저장하자.
시간대는 아무거나 상관없다.


NetCDF4 설치

NetCDF4 파일을 읽기 위해서는 NetCDF4를 읽을 수 있는 라이브러리가 필요하다.

마찬가지로 설치하도록 하자.

conda install -c anaconda netcdf4


NetCDF4 파일 읽기

NetCDF4 모듈의 설명서는 다음의 링크에 있다.

위의 링크를 참조하면 NetCDF4 파일을 다음과 같이 읽거나 쓸 수 있다고 한다.

>>> from netCDF4 import Dataset
>>> rootgrp = Dataset("test.nc", "w", format="NETCDF4")
>>> print(rootgrp.data_model)
NETCDF4
>>> rootgrp.close()

우리는 데이터를 읽고자 하므로 "w"가 아닌 "r"로 바꿔주자.

이 후 한번 출력해보면 다음과 같이 나온다.

>>> from netCDF4 import Dataset
>>> nc_data = Dataset("hycom_glbv_930_2019010112_t000_ts3z_r.nc",\
                      "r", format="NETCDF4")
>>> print(nc_data)

<class 'netCDF4._netCDF4.Dataset'>
root group (NETCDF3_64BIT_OFFSET data model, file format NETCDF3):
    classification_level: UNCLASSIFIED
    distribution_statement: Approved for public release. Distribution unlimited.
    downgrade_date: not applicable
    classification_authority: not applicable
    institution: Naval Oceanographic Office
    source: HYCOM archive file
    history: Wed Sep 18 16:05:41 2019: ncks -d lon,115.,155. -d lat,18.,58. hycom_glbv_930_2019010112_t000_ts3z.nc hycom_glbv_930_2019010112_t000_ts3z_r.nc
archv2ncdf3z
    field_type: instantaneous
    Conventions: CF-1.6 NAVO_netcdf_v1.1
    NCO: 4.7.2
    dimensions(sizes): depth(40), lat(726), lon(500), time(1)
    variables(dimensions): float64 depth(depth), float64 lat(lat), float64 lon(lon), int16 salinity(time,depth,lat,lon), int16 salinity_bottom(time,lat,lon), float64 tau(time), float64 time(time), int16 water_temp(time,depth,lat,lon), int16 water_temp_bottom(time,lat,lon)
    groups: 

파일의 기본적인 정보(메타 데이터)가 전부 나오는데, 예를 들면 차원은 깊이, 위도, 경도, 시간 총 4개이며, 깊이는 40개, 위도는 726개, 경도는 500개, 시간은 1개가 있다는 것을 알 수 있다. 또한, 이 파일이 가지고 있는 데이터로는 깊이, 위도, 경도 이외에도 염분, 해저 염분, 시간 간격, 시간, 수온, 해저 수온이 있다.

우리가 필요한 것은 해수면 온도이므로, depth를 한 번 살펴보자

depth의 메타 데이터는 다음과 같이 볼 수 있다.

>>> print(nc_data['depth'])
<class 'netCDF4._netCDF4.Variable'>
float64 depth(depth)
    long_name: Depth
    standard_name: depth
    units: m
    positive: down
    axis: Z
    NAVO_code: 5
unlimited dimensions: 
current shape = (40,)
filling on, default _FillValue of 9.969209968386869e+36 used

또한, 데이터는 다음과 같이 뽑아볼 수 있다.

>>> print(nc_data['depth'][:])
[0.00e+00 2.00e+00 4.00e+00 6.00e+00 8.00e+00 1.00e+01 1.20e+01 1.50e+01
 2.00e+01 2.50e+01 3.00e+01 3.50e+01 4.00e+01 4.50e+01 5.00e+01 6.00e+01
 7.00e+01 8.00e+01 9.00e+01 1.00e+02 1.25e+02 1.50e+02 2.00e+02 2.50e+02
 3.00e+02 3.50e+02 4.00e+02 5.00e+02 6.00e+02 7.00e+02 8.00e+02 9.00e+02
 1.00e+03 1.25e+03 1.50e+03 2.00e+03 2.50e+03 3.00e+03 4.00e+03 5.00e+03]

해수면은 0번째 index에 있는 것을 알 수 있다.

nc_data = Dataset("hycom_glbv_930_2019010112_t000_ts3z_r.nc",\
                  "r", format="NETCDF4")
nc_data2 = Dataset("hycom_glbv_930_2019010112_t000_uv3z_r.nc",\
                  "r", format="NETCDF4")

depth = nc_data['depth'][:]             ## 수심
lat = nc_data['lat'][:]                 ## 위도
lon = nc_data['lon'][:]                 ## 경도

water_temp = nc_data['water_temp'][:]   ## 수온 데이터
sal = nc_data['salinity'][:]            ## 염분 데이터
water_u = nc_data2['water_u'][:]        ## 유향/유속 U
water_v = nc_data2['water_v'][:]        ## 유향/유속 V

water_temp = water_temp[0,0]
water_u = water_u[0,0]
water_v = water_v[0,0]

lon, lat = np.meshgrid(lon, lat)


수온 가시화

import matplotlib.pyplot as plt
fig, ax = plt.subplots(1, 1, figsize=(11,10))
fig.patch.set_facecolor('w')

# 수온 Contourf
water_temp_plot = ax.contourf(lon, lat, water_temp,\
                              levels=50, cmap='jet')
fig.colorbar(water_temp_plot, ticks=list(range(0,31,5)))
plt.show()

water_temp


유속, 유향 가시화

여기에 UV를 추가해주자

ax.quiver(lon, lat, water_u, water_v,\
          pivot='mid', scale=40)
plt.show()

다만 이렇게 하면 quiver가 너무 많아서 그림이 지저분해지므로 step을 주자

step = 5
ax.quiver(lon[::step,::step], lat[::step,::step],
           water_u[::step,::step], water_v[::step,::step],
           pivot='mid', scale=40, )
plt.show()

ts_uv

여기까지도 꽤나 이쁘게 보이지만 다음 포스트에서는 여기에 추가로 지도를 추가해보겠다.